diff --git a/.mailmap b/.mailmap index edcac87e76c8c7fe9020943bdce012f7e47dc962..83d7e750c2fc89e60986049ec475d93eb1f7bb8b 100644 --- a/.mailmap +++ b/.mailmap @@ -196,7 +196,8 @@ Oleksij Rempel Oleksij Rempel Paolo 'Blaisorblade' Giarrusso Patrick Mochel -Paul Burton +Paul Burton +Paul Burton Peter A Jonsson Peter Oruba Peter Oruba @@ -229,6 +230,7 @@ Shuah Khan Shuah Khan Shuah Khan Shuah Khan +Simon Arlott Simon Kelley Stéphane Witzmann Stephen Hemminger diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst index 17ea3fecddaa50ac1a1e8af59f222105622b1720..5a09661330fccfceedcb4e5879535d30b51697d3 100644 --- a/Documentation/arm64/silicon-errata.rst +++ b/Documentation/arm64/silicon-errata.rst @@ -91,6 +91,11 @@ stable kernels. | ARM | MMU-500 | #841119,826419 | N/A | +----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+ +| Broadcom | Brahma-B53 | N/A | ARM64_ERRATUM_845719 | ++----------------+-----------------+-----------------+-----------------------------+ +| Broadcom | Brahma-B53 | N/A | ARM64_ERRATUM_843419 | ++----------------+-----------------+-----------------+-----------------------------+ ++----------------+-----------------+-----------------+-----------------------------+ | Cavium | ThunderX ITS | #22375,24313 | CAVIUM_ERRATUM_22375 | +----------------+-----------------+-----------------+-----------------------------+ | Cavium | ThunderX ITS | #23144 | CAVIUM_ERRATUM_23144 | @@ -107,6 +112,8 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | Cavium | ThunderX2 SMMUv3| #126 | N/A | +----------------+-----------------+-----------------+-----------------------------+ +| Cavium | ThunderX2 Core | #219 | CAVIUM_TX2_ERRATUM_219 | ++----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+ | Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 | +----------------+-----------------+-----------------+-----------------------------+ @@ -124,7 +131,7 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | +----------------+-----------------+-----------------+-----------------------------+ -| Qualcomm Tech. | Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 | +| Qualcomm Tech. | Kryo/Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 | +----------------+-----------------+-----------------+-----------------------------+ | Qualcomm Tech. | QDF2400 ITS | E0065 | QCOM_QDF2400_ERRATUM_0065 | +----------------+-----------------+-----------------+-----------------------------+ diff --git a/Documentation/block/index.rst b/Documentation/block/index.rst index 3fa7a52fafa468023db19a219376c7505d7fdba5..026addfc69bc9743182cc6a594cf6952c9aa6f02 100644 --- a/Documentation/block/index.rst +++ b/Documentation/block/index.rst @@ -14,6 +14,7 @@ Block cmdline-partition data-integrity deadline-iosched + inline-encryption ioprio kyber-iosched null_blk diff --git a/Documentation/block/inline-encryption.rst b/Documentation/block/inline-encryption.rst new file mode 100644 index 0000000000000000000000000000000000000000..202826cee95e67b8cccab288053dd6486e265b3d --- /dev/null +++ b/Documentation/block/inline-encryption.rst @@ -0,0 +1,183 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================= +Inline Encryption +================= + +Objective +========= + +We want to support inline encryption (IE) in the kernel. +To allow for testing, we also want a crypto API fallback when actual +IE hardware is absent. We also want IE to work with layered devices +like dm and loopback (i.e. we want to be able to use the IE hardware +of the underlying devices if present, or else fall back to crypto API +en/decryption). + + +Constraints and notes +===================== + +- IE hardware have a limited number of "keyslots" that can be programmed + with an encryption context (key, algorithm, data unit size, etc.) at any time. + One can specify a keyslot in a data request made to the device, and the + device will en/decrypt the data using the encryption context programmed into + that specified keyslot. When possible, we want to make multiple requests with + the same encryption context share the same keyslot. + +- We need a way for filesystems to specify an encryption context to use for + en/decrypting a struct bio, and a device driver (like UFS) needs to be able + to use that encryption context when it processes the bio. + +- We need a way for device drivers to expose their capabilities in a unified + way to the upper layers. + + +Design +====== + +We add a struct bio_crypt_ctx to struct bio that can represent an +encryption context, because we need to be able to pass this encryption +context from the FS layer to the device driver to act upon. + +While IE hardware works on the notion of keyslots, the FS layer has no +knowledge of keyslots - it simply wants to specify an encryption context to +use while en/decrypting a bio. + +We introduce a keyslot manager (KSM) that handles the translation from +encryption contexts specified by the FS to keyslots on the IE hardware. +This KSM also serves as the way IE hardware can expose their capabilities to +upper layers. The generic mode of operation is: each device driver that wants +to support IE will construct a KSM and set it up in its struct request_queue. +Upper layers that want to use IE on this device can then use this KSM in +the device's struct request_queue to translate an encryption context into +a keyslot. The presence of the KSM in the request queue shall be used to mean +that the device supports IE. + +On the device driver end of the interface, the device driver needs to tell the +KSM how to actually manipulate the IE hardware in the device to do things like +programming the crypto key into the IE hardware into a particular keyslot. All +this is achieved through the :c:type:`struct keyslot_mgmt_ll_ops` that the +device driver passes to the KSM when creating it. + +It uses refcounts to track which keyslots are idle (either they have no +encryption context programmed, or there are no in-flight struct bios +referencing that keyslot). When a new encryption context needs a keyslot, it +tries to find a keyslot that has already been programmed with the same +encryption context, and if there is no such keyslot, it evicts the least +recently used idle keyslot and programs the new encryption context into that +one. If no idle keyslots are available, then the caller will sleep until there +is at least one. + + +Blk-crypto +========== + +The above is sufficient for simple cases, but does not work if there is a +need for a crypto API fallback, or if we are want to use IE with layered +devices. To these ends, we introduce blk-crypto. Blk-crypto allows us to +present a unified view of encryption to the FS (so FS only needs to specify +an encryption context and not worry about keyslots at all), and blk-crypto +can decide whether to delegate the en/decryption to IE hardware or to the +crypto API. Blk-crypto maintains an internal KSM that serves as the crypto +API fallback. + +Blk-crypto needs to ensure that the encryption context is programmed into the +"correct" keyslot manager for IE. If a bio is submitted to a layered device +that eventually passes the bio down to a device that really does support IE, we +want the encryption context to be programmed into a keyslot for the KSM of the +device with IE support. However, blk-crypto does not know a priori whether a +particular device is the final device in the layering structure for a bio or +not. So in the case that a particular device does not support IE, since it is +possibly the final destination device for the bio, if the bio requires +encryption (i.e. the bio is doing a write operation), blk-crypto must fallback +to the crypto API *before* sending the bio to the device. + +Blk-crypto ensures that: + +- The bio's encryption context is programmed into a keyslot in the KSM of the + request queue that the bio is being submitted to (or the crypto API fallback + KSM if the request queue doesn't have a KSM), and that the ``processing_ksm`` + in the ``bi_crypt_context`` is set to this KSM + +- That the bio has its own individual reference to the keyslot in this KSM. + Once the bio passes through blk-crypto, its encryption context is programmed + in some KSM. The "its own individual reference to the keyslot" ensures that + keyslots can be released by each bio independently of other bios while + ensuring that the bio has a valid reference to the keyslot when, for e.g., the + crypto API fallback KSM in blk-crypto performs crypto on the device's behalf. + The individual references are ensured by increasing the refcount for the + keyslot in the ``processing_ksm`` when a bio with a programmed encryption + context is cloned. + + +What blk-crypto does on bio submission +-------------------------------------- + +**Case 1:** blk-crypto is given a bio with only an encryption context that hasn't +been programmed into any keyslot in any KSM (for e.g. a bio from the FS). + In this case, blk-crypto will program the encryption context into the KSM of the + request queue the bio is being submitted to (and if this KSM does not exist, + then it will program it into blk-crypto's internal KSM for crypto API + fallback). The KSM that this encryption context was programmed into is stored + as the ``processing_ksm`` in the bio's ``bi_crypt_context``. + +**Case 2:** blk-crypto is given a bio whose encryption context has already been +programmed into a keyslot in the *crypto API fallback* KSM. + In this case, blk-crypto does nothing; it treats the bio as not having + specified an encryption context. Note that we cannot do here what we will do + in Case 3 because we would have already encrypted the bio via the crypto API + by this point. + +**Case 3:** blk-crypto is given a bio whose encryption context has already been +programmed into a keyslot in some KSM (that is *not* the crypto API fallback +KSM). + In this case, blk-crypto first releases that keyslot from that KSM and then + treats the bio as in Case 1. + +This way, when a device driver is processing a bio, it can be sure that +the bio's encryption context has been programmed into some KSM (either the +device driver's request queue's KSM, or blk-crypto's crypto API fallback KSM). +It then simply needs to check if the bio's processing_ksm is the device's +request queue's KSM. If so, then it should proceed with IE. If not, it should +simply do nothing with respect to crypto, because some other KSM (perhaps the +blk-crypto crypto API fallback KSM) is handling the en/decryption. + +Blk-crypto will release the keyslot that is being held by the bio (and also +decrypt it if the bio is using the crypto API fallback KSM) once +``bio_remaining_done`` returns true for the bio. + + +Layered Devices +=============== + +Layered devices that wish to support IE need to create their own keyslot +manager for their request queue, and expose whatever functionality they choose. +When a layered device wants to pass a bio to another layer (either by +resubmitting the same bio, or by submitting a clone), it doesn't need to do +anything special because the bio (or the clone) will once again pass through +blk-crypto, which will work as described in Case 3. If a layered device wants +for some reason to do the IO by itself instead of passing it on to a child +device, but it also chose to expose IE capabilities by setting up a KSM in its +request queue, it is then responsible for en/decrypting the data itself. In +such cases, the device can choose to call the blk-crypto function +``blk_crypto_fallback_to_kernel_crypto_api`` (TODO: Not yet implemented), which will +cause the en/decryption to be done via the crypto API fallback. + + +Future Optimizations for layered devices +======================================== + +Creating a keyslot manager for the layered device uses up memory for each +keyslot, and in general, a layered device (like dm-linear) merely passes the +request on to a "child" device, so the keyslots in the layered device itself +might be completely unused. We can instead define a new type of KSM; the +"passthrough KSM", that layered devices can use to let blk-crypto know that +this layered device *will* pass the bio to some child device (and hence +through blk-crypto again, at which point blk-crypto can program the encryption +context, instead of programming it into the layered device's KSM). Again, if +the device "lies" and decides to do the IO itself instead of passing it on to +a child device, it is responsible for doing the en/decryption (and can choose +to call ``blk_crypto_fallback_to_kernel_crypto_api``). Another use case for the +"passthrough KSM" is for IE devices that want to manage their own keyslots/do +not have a limited number of keyslots. diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst index b72d07d70239c421e683c9df06411f728e114a9e..525296121d8953add4af9e7144a2eb2d6ba27b1e 100644 --- a/Documentation/dev-tools/kasan.rst +++ b/Documentation/dev-tools/kasan.rst @@ -41,6 +41,9 @@ smaller binary while the latter is 1.1 - 2 times faster. Both KASAN modes work with both SLUB and SLAB memory allocators. For better bug detection and nicer reporting, enable CONFIG_STACKTRACE. +To augment reports with last allocation and freeing stack of the physical page, +it is recommended to enable also CONFIG_PAGE_OWNER and boot with page_owner=on. + To disable instrumentation for specific files or directories, add a line similar to the following to the respective kernel Makefile: diff --git a/Documentation/driver-api/driver-model/driver.rst b/Documentation/driver-api/driver-model/driver.rst index 11d281506a0415219e945c49684b2977ea873d7e..baa6a85c82871b40f9aa43bd505efc89febedeb2 100644 --- a/Documentation/driver-api/driver-model/driver.rst +++ b/Documentation/driver-api/driver-model/driver.rst @@ -169,6 +169,49 @@ A driver's probe() may return a negative errno value to indicate that the driver did not bind to this device, in which case it should have released all resources it allocated:: + void (*sync_state)(struct device *dev); + +sync_state is called only once for a device. It's called when all the consumer +devices of the device have successfully probed. The list of consumers of the +device is obtained by looking at the device links connecting that device to its +consumer devices. + +The first attempt to call sync_state() is made during late_initcall_sync() to +give firmware and drivers time to link devices to each other. During the first +attempt at calling sync_state(), if all the consumers of the device at that +point in time have already probed successfully, sync_state() is called right +away. If there are no consumers of the device during the first attempt, that +too is considered as "all consumers of the device have probed" and sync_state() +is called right away. + +If during the first attempt at calling sync_state() for a device, there are +still consumers that haven't probed successfully, the sync_state() call is +postponed and reattempted in the future only when one or more consumers of the +device probe successfully. If during the reattempt, the driver core finds that +there are one or more consumers of the device that haven't probed yet, then +sync_state() call is postponed again. + +A typical use case for sync_state() is to have the kernel cleanly take over +management of devices from the bootloader. For example, if a device is left on +and at a particular hardware configuration by the bootloader, the device's +driver might need to keep the device in the boot configuration until all the +consumers of the device have probed. Once all the consumers of the device have +probed, the device's driver can synchronize the hardware state of the device to +match the aggregated software state requested by all the consumers. Hence the +name sync_state(). + +While obvious examples of resources that can benefit from sync_state() include +resources such as regulator, sync_state() can also be useful for complex +resources like IOMMUs. For example, IOMMUs with multiple consumers (devices +whose addresses are remapped by the IOMMU) might need to keep their mappings +fixed at (or additive to) the boot configuration until all its consumers have +probed. + +While the typical use case for sync_state() is to have the kernel cleanly take +over management of devices from the bootloader, the usage of sync_state() is +not restricted to that. Use it whenever it makes sense to take an action after +all the consumers of a device have probed. + int (*remove) (struct device *dev); remove is called to unbind a driver from a device. This may be diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index 8a0700af959672568b7713dbb6e2f8c82449e200..471a511c75088d7e5b3528f055d420a3d59e22d5 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -256,13 +256,8 @@ alternative master keys or to support rotating master keys. Instead, the master keys may be wrapped in userspace, e.g. as is done by the `fscrypt `_ tool. -Including the inode number in the IVs was considered. However, it was -rejected as it would have prevented ext4 filesystems from being -resized, and by itself still wouldn't have been sufficient to prevent -the same key from being directly reused for both XTS and CTS-CBC. - -DIRECT_KEY and per-mode keys ----------------------------- +DIRECT_KEY policies +------------------- The Adiantum encryption mode (see `Encryption modes and usage`_) is suitable for both contents and filenames encryption, and it accepts @@ -285,6 +280,21 @@ IV. Moreover: key derived using the KDF. Users may use the same master key for other v2 encryption policies. +IV_INO_LBLK_64 policies +----------------------- + +When FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 is set in the fscrypt policy, +the encryption keys are derived from the master key, encryption mode +number, and filesystem UUID. This normally results in all files +protected by the same master key sharing a single contents encryption +key and a single filenames encryption key. To still encrypt different +files' data differently, inode numbers are included in the IVs. +Consequently, shrinking the filesystem may not be allowed. + +This format is optimized for use with inline encryption hardware +compliant with the UFS or eMMC standards, which support only 64 IV +bits per I/O request and may have only a small number of keyslots. + Key identifiers --------------- @@ -308,8 +318,9 @@ If unsure, you should use the (AES-256-XTS, AES-256-CTS-CBC) pair. AES-128-CBC was added only for low-powered embedded devices with crypto accelerators such as CAAM or CESA that do not support XTS. To -use AES-128-CBC, CONFIG_CRYPTO_SHA256 (or another SHA-256 -implementation) must be enabled so that ESSIV can be used. +use AES-128-CBC, CONFIG_CRYPTO_ESSIV and CONFIG_CRYPTO_SHA256 (or +another SHA-256 implementation) must be enabled so that ESSIV can be +used. Adiantum is a (primarily) stream cipher-based mode that is fast even on CPUs without dedicated crypto instructions. It's also a true @@ -341,10 +352,16 @@ a little endian number, except that: is encrypted with AES-256 where the AES-256 key is the SHA-256 hash of the file's data encryption key. -- In the "direct key" configuration (FSCRYPT_POLICY_FLAG_DIRECT_KEY - set in the fscrypt_policy), the file's nonce is also appended to the - IV. Currently this is only allowed with the Adiantum encryption - mode. +- With `DIRECT_KEY policies`_, the file's nonce is appended to the IV. + Currently this is only allowed with the Adiantum encryption mode. + +- With `IV_INO_LBLK_64 policies`_, the logical block number is limited + to 32 bits and is placed in bits 0-31 of the IV. The inode number + (which is also limited to 32 bits) is placed in bits 32-63. + +Note that because file logical block numbers are included in the IVs, +filesystems must enforce that blocks are never shifted around within +encrypted files, e.g. via "collapse range" or "insert range". Filenames encryption -------------------- @@ -354,10 +371,10 @@ the requirements to retain support for efficient directory lookups and filenames of up to 255 bytes, the same IV is used for every filename in a directory. -However, each encrypted directory still uses a unique key; or -alternatively (for the "direct key" configuration) has the file's -nonce included in the IVs. Thus, IV reuse is limited to within a -single directory. +However, each encrypted directory still uses a unique key, or +alternatively has the file's nonce (for `DIRECT_KEY policies`_) or +inode number (for `IV_INO_LBLK_64 policies`_) included in the IVs. +Thus, IV reuse is limited to within a single directory. With CTS-CBC, the IV reuse means that when the plaintext filenames share a common prefix at least as long as the cipher block size (16 @@ -431,12 +448,15 @@ This structure must be initialized as follows: (1) for ``contents_encryption_mode`` and FSCRYPT_MODE_AES_256_CTS (4) for ``filenames_encryption_mode``. -- ``flags`` must contain a value from ```` which - identifies the amount of NUL-padding to use when encrypting - filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3). - Additionally, if the encryption modes are both - FSCRYPT_MODE_ADIANTUM, this can contain - FSCRYPT_POLICY_FLAG_DIRECT_KEY; see `DIRECT_KEY and per-mode keys`_. +- ``flags`` contains optional flags from ````: + + - FSCRYPT_POLICY_FLAGS_PAD_*: The amount of NUL padding to use when + encrypting filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 + (0x3). + - FSCRYPT_POLICY_FLAG_DIRECT_KEY: See `DIRECT_KEY policies`_. + - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64: See `IV_INO_LBLK_64 + policies`_. This is mutually exclusive with DIRECT_KEY and is not + supported on v1 policies. - For v2 encryption policies, ``__reserved`` must be zeroed. @@ -1089,7 +1109,7 @@ policy structs (see `Setting an encryption policy`_), except that the context structs also contain a nonce. The nonce is randomly generated by the kernel and is used as KDF input or as a tweak to cause different files to be encrypted differently; see `Per-file keys`_ and -`DIRECT_KEY and per-mode keys`_. +`DIRECT_KEY policies`_. Data path changes ----------------- diff --git a/Documentation/ioctl/ioctl-number.rst b/Documentation/ioctl/ioctl-number.rst index bef79cd4c6b4d35566a629059c5d7304b4c34e13..4ef86433bd6773b14685972b65e8695406365e58 100644 --- a/Documentation/ioctl/ioctl-number.rst +++ b/Documentation/ioctl/ioctl-number.rst @@ -233,6 +233,7 @@ Code Seq# Include File Comments 'f' 00-0F fs/ext4/ext4.h conflict! 'f' 00-0F linux/fs.h conflict! 'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict! +'f' 13-27 linux/fscrypt.h 'f' 81-8F linux/fsverity.h 'g' 00-0F linux/usb/gadgetfs.h 'g' 20-2F linux/usb/g_printer.h diff --git a/Documentation/kbuild/reproducible-builds.rst b/Documentation/kbuild/reproducible-builds.rst index ab92e98c89c86cfc8bb5ef428167121b5f5290d6..503393854e2e2a7bbe12d51de0c848f293ea4fe4 100644 --- a/Documentation/kbuild/reproducible-builds.rst +++ b/Documentation/kbuild/reproducible-builds.rst @@ -16,16 +16,21 @@ the kernel may be unreproducible, and how to avoid them. Timestamps ---------- -The kernel embeds a timestamp in two places: +The kernel embeds timestamps in three places: * The version string exposed by ``uname()`` and included in ``/proc/version`` * File timestamps in the embedded initramfs -By default the timestamp is the current time. This must be overridden -using the `KBUILD_BUILD_TIMESTAMP`_ variable. If you are building -from a git commit, you could use its commit date. +* If enabled via ``CONFIG_IKHEADERS``, file timestamps of kernel + headers embedded in the kernel or respective module, + exposed via ``/sys/kernel/kheaders.tar.xz`` + +By default the timestamp is the current time and in the case of +``kheaders`` the various files' modification times. This must +be overridden using the `KBUILD_BUILD_TIMESTAMP`_ variable. +If you are building from a git commit, you could use its commit date. The kernel does *not* use the ``__DATE__`` and ``__TIME__`` macros, and enables warnings if they are used. If you incorporate external diff --git a/Documentation/networking/device_drivers/intel/e100.rst b/Documentation/networking/device_drivers/intel/e100.rst index 2b9f4887beda8970e18d7f93feef61504307668a..caf023cc88dead5ccf6a4f9bb4d95a4e6eb5296f 100644 --- a/Documentation/networking/device_drivers/intel/e100.rst +++ b/Documentation/networking/device_drivers/intel/e100.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -============================================================== -Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters -============================================================== +============================================================= +Linux Base Driver for the Intel(R) PRO/100 Family of Adapters +============================================================= June 1, 2018 @@ -21,7 +21,7 @@ Contents In This Release =============== -This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of +This file describes the Linux Base Driver for the Intel(R) PRO/100 Family of Adapters. This driver includes support for Itanium(R)2-based systems. For questions related to hardware requirements, refer to the documentation @@ -138,9 +138,9 @@ version 1.6 or later is required for this functionality. The latest release of ethtool can be found from https://www.kernel.org/pub/software/network/ethtool/ -Enabling Wake on LAN* (WoL) ---------------------------- -WoL is provided through the ethtool* utility. For instructions on +Enabling Wake on LAN (WoL) +-------------------------- +WoL is provided through the ethtool utility. For instructions on enabling WoL with ethtool, refer to the ethtool man page. WoL will be enabled on the system during the next shut down or reboot. For this driver version, in order to enable WoL, the e100 driver must be loaded diff --git a/Documentation/networking/device_drivers/intel/e1000.rst b/Documentation/networking/device_drivers/intel/e1000.rst index 956560b6e745ce6f45130fd24cbd0593f946c327..4aaae0f7d6ba7fb3b5290a05599605bff586193a 100644 --- a/Documentation/networking/device_drivers/intel/e1000.rst +++ b/Documentation/networking/device_drivers/intel/e1000.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -=========================================================== -Linux* Base Driver for Intel(R) Ethernet Network Connection -=========================================================== +========================================================== +Linux Base Driver for Intel(R) Ethernet Network Connection +========================================================== Intel Gigabit Linux driver. Copyright(c) 1999 - 2013 Intel Corporation. @@ -438,10 +438,10 @@ ethtool The latest release of ethtool can be found from https://www.kernel.org/pub/software/network/ethtool/ -Enabling Wake on LAN* (WoL) ---------------------------- +Enabling Wake on LAN (WoL) +-------------------------- - WoL is configured through the ethtool* utility. + WoL is configured through the ethtool utility. WoL will be enabled on the system during the next shut down or reboot. For this driver version, in order to enable WoL, the e1000 driver must be diff --git a/Documentation/networking/device_drivers/intel/e1000e.rst b/Documentation/networking/device_drivers/intel/e1000e.rst index 01999f05509c425010b5c944d4ac2932da00ad5a..f49cd370e7bf622d3c8bae7a56a86f4360499400 100644 --- a/Documentation/networking/device_drivers/intel/e1000e.rst +++ b/Documentation/networking/device_drivers/intel/e1000e.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -====================================================== -Linux* Driver for Intel(R) Ethernet Network Connection -====================================================== +===================================================== +Linux Driver for Intel(R) Ethernet Network Connection +===================================================== Intel Gigabit Linux driver. Copyright(c) 2008-2018 Intel Corporation. @@ -338,7 +338,7 @@ and higher cannot be forced. Use the autonegotiation advertising setting to manually set devices for 1 Gbps and higher. Speed, duplex, and autonegotiation advertising are configured through the -ethtool* utility. +ethtool utility. Caution: Only experienced network administrators should force speed and duplex or change autonegotiation advertising manually. The settings at the switch must @@ -351,9 +351,9 @@ will not attempt to auto-negotiate with its link partner since those adapters operate only in full duplex and only at their native speed. -Enabling Wake on LAN* (WoL) ---------------------------- -WoL is configured through the ethtool* utility. +Enabling Wake on LAN (WoL) +-------------------------- +WoL is configured through the ethtool utility. WoL will be enabled on the system during the next shut down or reboot. For this driver version, in order to enable WoL, the e1000e driver must be loaded diff --git a/Documentation/networking/device_drivers/intel/fm10k.rst b/Documentation/networking/device_drivers/intel/fm10k.rst index ac3269e34f552206f206a31231e8338f5426f60d..4d279e64e221e6475b291e98c7fde7a3a882caaf 100644 --- a/Documentation/networking/device_drivers/intel/fm10k.rst +++ b/Documentation/networking/device_drivers/intel/fm10k.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -============================================================== -Linux* Base Driver for Intel(R) Ethernet Multi-host Controller -============================================================== +============================================================= +Linux Base Driver for Intel(R) Ethernet Multi-host Controller +============================================================= August 20, 2018 Copyright(c) 2015-2018 Intel Corporation. @@ -120,8 +120,8 @@ rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r Known Issues/Troubleshooting ============================ -Enabling SR-IOV in a 64-bit Microsoft* Windows Server* 2012/R2 guest OS under Linux KVM ---------------------------------------------------------------------------------------- +Enabling SR-IOV in a 64-bit Microsoft Windows Server 2012/R2 guest OS under Linux KVM +------------------------------------------------------------------------------------- KVM Hypervisor/VMM supports direct assignment of a PCIe device to a VM. This includes traditional PCIe devices, as well as SR-IOV-capable devices based on the Intel Ethernet Controller XL710. diff --git a/Documentation/networking/device_drivers/intel/i40e.rst b/Documentation/networking/device_drivers/intel/i40e.rst index 848fd388fa6e01403f7d1f67d2256463f4ebe228..8a9b18573688d87c9fc521d00b129bd7ae7c61b7 100644 --- a/Documentation/networking/device_drivers/intel/i40e.rst +++ b/Documentation/networking/device_drivers/intel/i40e.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -================================================================== -Linux* Base Driver for the Intel(R) Ethernet Controller 700 Series -================================================================== +================================================================= +Linux Base Driver for the Intel(R) Ethernet Controller 700 Series +================================================================= Intel 40 Gigabit Linux driver. Copyright(c) 1999-2018 Intel Corporation. @@ -384,7 +384,7 @@ NOTE: You cannot set the speed for devices based on the Intel(R) Ethernet Network Adapter XXV710 based devices. Speed, duplex, and autonegotiation advertising are configured through the -ethtool* utility. +ethtool utility. Caution: Only experienced network administrators should force speed and duplex or change autonegotiation advertising manually. The settings at the switch must diff --git a/Documentation/networking/device_drivers/intel/iavf.rst b/Documentation/networking/device_drivers/intel/iavf.rst index cfc08842e32c6e4c00839c13a2861c5e32bb890d..84ac7e75f36313a5343709f65b1bc9bcef8fdc19 100644 --- a/Documentation/networking/device_drivers/intel/iavf.rst +++ b/Documentation/networking/device_drivers/intel/iavf.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -================================================================== -Linux* Base Driver for Intel(R) Ethernet Adaptive Virtual Function -================================================================== +================================================================= +Linux Base Driver for Intel(R) Ethernet Adaptive Virtual Function +================================================================= Intel Ethernet Adaptive Virtual Function Linux driver. Copyright(c) 2013-2018 Intel Corporation. @@ -19,7 +19,7 @@ Contents Overview ======== -This file describes the iavf Linux* Base Driver. This driver was formerly +This file describes the iavf Linux Base Driver. This driver was formerly called i40evf. The iavf driver supports the below mentioned virtual function devices and diff --git a/Documentation/networking/device_drivers/intel/ice.rst b/Documentation/networking/device_drivers/intel/ice.rst index c220aa2711c67c3983ae1090a54973868837b95a..ee43ea57d4430ca78b98efa2e7807a3ec4dbaa42 100644 --- a/Documentation/networking/device_drivers/intel/ice.rst +++ b/Documentation/networking/device_drivers/intel/ice.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -=================================================================== -Linux* Base Driver for the Intel(R) Ethernet Connection E800 Series -=================================================================== +================================================================== +Linux Base Driver for the Intel(R) Ethernet Connection E800 Series +================================================================== Intel ice Linux driver. Copyright(c) 2018 Intel Corporation. diff --git a/Documentation/networking/device_drivers/intel/igb.rst b/Documentation/networking/device_drivers/intel/igb.rst index fc8cfaa5dcfaca38d70b31f2a0e1df8134d380a7..87e560fe5eaaba65bfe1840504129afb533671ae 100644 --- a/Documentation/networking/device_drivers/intel/igb.rst +++ b/Documentation/networking/device_drivers/intel/igb.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -=========================================================== -Linux* Base Driver for Intel(R) Ethernet Network Connection -=========================================================== +========================================================== +Linux Base Driver for Intel(R) Ethernet Network Connection +========================================================== Intel Gigabit Linux driver. Copyright(c) 1999-2018 Intel Corporation. @@ -129,9 +129,9 @@ version is required for this functionality. Download it at: https://www.kernel.org/pub/software/network/ethtool/ -Enabling Wake on LAN* (WoL) ---------------------------- -WoL is configured through the ethtool* utility. +Enabling Wake on LAN (WoL) +-------------------------- +WoL is configured through the ethtool utility. WoL will be enabled on the system during the next shut down or reboot. For this driver version, in order to enable WoL, the igb driver must be loaded diff --git a/Documentation/networking/device_drivers/intel/igbvf.rst b/Documentation/networking/device_drivers/intel/igbvf.rst index 9cddabe8108ead0e2bcd93d71626ba8214244f8a..557fc020ef31e0f3c403bd38dedb75c0582d2fe5 100644 --- a/Documentation/networking/device_drivers/intel/igbvf.rst +++ b/Documentation/networking/device_drivers/intel/igbvf.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -============================================================ -Linux* Base Virtual Function Driver for Intel(R) 1G Ethernet -============================================================ +=========================================================== +Linux Base Virtual Function Driver for Intel(R) 1G Ethernet +=========================================================== Intel Gigabit Virtual Function Linux driver. Copyright(c) 1999-2018 Intel Corporation. diff --git a/Documentation/networking/device_drivers/intel/ixgbe.rst b/Documentation/networking/device_drivers/intel/ixgbe.rst index c7d25483fedb20c049c645835ec13ad7600acfce..f1d5233e5e510929ba6d3f4f8cd049dc8767677c 100644 --- a/Documentation/networking/device_drivers/intel/ixgbe.rst +++ b/Documentation/networking/device_drivers/intel/ixgbe.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -============================================================================= -Linux* Base Driver for the Intel(R) Ethernet 10 Gigabit PCI Express Adapters -============================================================================= +=========================================================================== +Linux Base Driver for the Intel(R) Ethernet 10 Gigabit PCI Express Adapters +=========================================================================== Intel 10 Gigabit Linux driver. Copyright(c) 1999-2018 Intel Corporation. @@ -519,8 +519,8 @@ The offload is also supported for ixgbe's VFs, but the VF must be set as Known Issues/Troubleshooting ============================ -Enabling SR-IOV in a 64-bit Microsoft* Windows Server* 2012/R2 guest OS ------------------------------------------------------------------------ +Enabling SR-IOV in a 64-bit Microsoft Windows Server 2012/R2 guest OS +--------------------------------------------------------------------- Linux KVM Hypervisor/VMM supports direct assignment of a PCIe device to a VM. This includes traditional PCIe devices, as well as SR-IOV-capable devices based on the Intel Ethernet Controller XL710. diff --git a/Documentation/networking/device_drivers/intel/ixgbevf.rst b/Documentation/networking/device_drivers/intel/ixgbevf.rst index 5d4977360157ed87b87b001c74bbe314c9fbe0d5..76bbde736f21546071167609294a83a91a2307fd 100644 --- a/Documentation/networking/device_drivers/intel/ixgbevf.rst +++ b/Documentation/networking/device_drivers/intel/ixgbevf.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -============================================================= -Linux* Base Virtual Function Driver for Intel(R) 10G Ethernet -============================================================= +============================================================ +Linux Base Virtual Function Driver for Intel(R) 10G Ethernet +============================================================ Intel 10 Gigabit Virtual Function Linux driver. Copyright(c) 1999-2018 Intel Corporation. diff --git a/Documentation/networking/device_drivers/pensando/ionic.rst b/Documentation/networking/device_drivers/pensando/ionic.rst index 67b6839d516b976d5c850d51d78dc6c5fcb64e1a..c17d680cf334aeebcb7aa905b01151b99e2a68f9 100644 --- a/Documentation/networking/device_drivers/pensando/ionic.rst +++ b/Documentation/networking/device_drivers/pensando/ionic.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -========================================================== -Linux* Driver for the Pensando(R) Ethernet adapter family -========================================================== +======================================================== +Linux Driver for the Pensando(R) Ethernet adapter family +======================================================== Pensando Linux Ethernet driver. Copyright(c) 2019 Pensando Systems, Inc @@ -36,8 +36,10 @@ Support ======= For general Linux networking support, please use the netdev mailing list, which is monitored by Pensando personnel:: + netdev@vger.kernel.org For more specific support needs, please use the Pensando driver support email:: - drivers@pensando.io + + drivers@pensando.io diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 49e95f438ed7571a93bceffdc17846c35dd64fca..8d4ad1d1ae26f11ffe0ff1db61c61f20b573b8b8 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -207,8 +207,8 @@ TCP variables: somaxconn - INTEGER Limit of socket listen() backlog, known in userspace as SOMAXCONN. - Defaults to 128. See also tcp_max_syn_backlog for additional tuning - for TCP sockets. + Defaults to 4096. (Was 128 before linux-5.4) + See also tcp_max_syn_backlog for additional tuning for TCP sockets. tcp_abort_on_overflow - BOOLEAN If listening service is too slow to accept new connections, @@ -408,11 +408,14 @@ tcp_max_orphans - INTEGER up to ~64K of unswappable memory. tcp_max_syn_backlog - INTEGER - Maximal number of remembered connection requests, which have not - received an acknowledgment from connecting client. + Maximal number of remembered connection requests (SYN_RECV), + which have not received an acknowledgment from connecting client. + This is a per-listener limit. The minimal value is 128 for low memory machines, and it will increase in proportion to the memory of machine. If server suffers from overload, try increasing this number. + Remember to also check /proc/sys/net/core/somaxconn + A SYN_RECV request socket consumes about 304 bytes of memory. tcp_max_tw_buckets - INTEGER Maximal number of timewait sockets held by system simultaneously. diff --git a/Documentation/networking/net_dim.txt b/Documentation/networking/net_dim.txt index 9cb31c5e2dcdf465e4efda3f8543c2857a7c3ec6..9bdb7d5a3ba3ae4974a4a5875313707d23476abf 100644 --- a/Documentation/networking/net_dim.txt +++ b/Documentation/networking/net_dim.txt @@ -92,16 +92,16 @@ under some conditions. Part III: Registering a Network Device to DIM ============================================== -Net DIM API exposes the main function net_dim(struct net_dim *dim, -struct net_dim_sample end_sample). This function is the entry point to the Net +Net DIM API exposes the main function net_dim(struct dim *dim, +struct dim_sample end_sample). This function is the entry point to the Net DIM algorithm and has to be called every time the driver would like to check if it should change interrupt moderation parameters. The driver should provide two -data structures: struct net_dim and struct net_dim_sample. Struct net_dim +data structures: struct dim and struct dim_sample. Struct dim describes the state of DIM for a specific object (RX queue, TX queue, other queues, etc.). This includes the current selected profile, previous data samples, the callback function provided by the driver and more. -Struct net_dim_sample describes a data sample, which will be compared to the -data sample stored in struct net_dim in order to decide on the algorithm's next +Struct dim_sample describes a data sample, which will be compared to the +data sample stored in struct dim in order to decide on the algorithm's next step. The sample should include bytes, packets and interrupts, measured by the driver. @@ -110,9 +110,9 @@ main net_dim() function. The recommended method is to call net_dim() on each interrupt. Since Net DIM has a built-in moderation and it might decide to skip iterations under certain conditions, there is no need to moderate the net_dim() calls as well. As mentioned above, the driver needs to provide an object of type -struct net_dim to the net_dim() function call. It is advised for each entity -using Net DIM to hold a struct net_dim as part of its data structure and use it -as the main Net DIM API object. The struct net_dim_sample should hold the latest +struct dim to the net_dim() function call. It is advised for each entity +using Net DIM to hold a struct dim as part of its data structure and use it +as the main Net DIM API object. The struct dim_sample should hold the latest bytes, packets and interrupts count. No need to perform any calculations, just include the raw data. @@ -132,19 +132,19 @@ usage is not complete but it should make the outline of the usage clear. my_driver.c: -#include +#include /* Callback for net DIM to schedule on a decision to change moderation */ void my_driver_do_dim_work(struct work_struct *work) { - /* Get struct net_dim from struct work_struct */ - struct net_dim *dim = container_of(work, struct net_dim, - work); + /* Get struct dim from struct work_struct */ + struct dim *dim = container_of(work, struct dim, + work); /* Do interrupt moderation related stuff */ ... /* Signal net DIM work is done and it should move to next iteration */ - dim->state = NET_DIM_START_MEASURE; + dim->state = DIM_START_MEASURE; } /* My driver's interrupt handler */ @@ -152,13 +152,13 @@ int my_driver_handle_interrupt(struct my_driver_entity *my_entity, ...) { ... /* A struct to hold current measured data */ - struct net_dim_sample dim_sample; + struct dim_sample dim_sample; ... /* Initiate data sample struct with current data */ - net_dim_sample(my_entity->events, - my_entity->packets, - my_entity->bytes, - &dim_sample); + dim_update_sample(my_entity->events, + my_entity->packets, + my_entity->bytes, + &dim_sample); /* Call net DIM */ net_dim(&my_entity->dim, dim_sample); ... diff --git a/MAINTAINERS b/MAINTAINERS index a69e6db80c79e0cd6fa319f3f7d5233b0d226d8d..cba1095547fd720f7ca08b4d6fe0ec9c1a9a9807 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2323,11 +2323,13 @@ F: drivers/edac/altera_edac. ARM/SPREADTRUM SoC SUPPORT M: Orson Zhai -M: Baolin Wang +M: Baolin Wang M: Chunyan Zhang S: Maintained F: arch/arm64/boot/dts/sprd N: sprd +N: sc27xx +N: sc2731 ARM/STI ARCHITECTURE M: Patrice Chotard @@ -3096,7 +3098,7 @@ S: Supported F: arch/arm64/net/ BPF JIT for MIPS (32-BIT AND 64-BIT) -M: Paul Burton +M: Paul Burton L: netdev@vger.kernel.org L: bpf@vger.kernel.org S: Maintained @@ -3183,7 +3185,7 @@ N: bcm216* N: kona F: arch/arm/mach-bcm/ -BROADCOM BCM2835 ARM ARCHITECTURE +BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE M: Eric Anholt M: Stefan Wahren L: bcm-kernel-feedback-list@broadcom.com @@ -3191,6 +3193,7 @@ L: linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) T: git git://github.com/anholt/linux S: Maintained +N: bcm2711 N: bcm2835 F: drivers/staging/vc04_services @@ -3237,8 +3240,6 @@ S: Maintained F: drivers/usb/gadget/udc/bcm63xx_udc.* BROADCOM BCM7XXX ARM ARCHITECTURE -M: Brian Norris -M: Gregory Fong M: Florian Fainelli M: bcm-kernel-feedback-list@broadcom.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -8001,7 +8002,7 @@ S: Maintained F: drivers/usb/atm/ueagle-atm.c IMGTEC ASCII LCD DRIVER -M: Paul Burton +M: Paul Burton S: Maintained F: Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt F: drivers/auxdisplay/img-ascii-lcd.c @@ -9122,7 +9123,7 @@ F: drivers/auxdisplay/ks0108.c F: include/linux/ks0108.h L3MDEV -M: David Ahern +M: David Ahern L: netdev@vger.kernel.org S: Maintained F: net/l3mdev @@ -10255,7 +10256,7 @@ MEDIATEK ETHERNET DRIVER M: Felix Fietkau M: John Crispin M: Sean Wang -M: Nelson Chang +M: Mark Lee L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/mediatek/ @@ -10828,7 +10829,7 @@ F: drivers/usb/image/microtek.* MIPS M: Ralf Baechle -M: Paul Burton +M: Paul Burton M: James Hogan L: linux-mips@vger.kernel.org W: http://www.linux-mips.org/ @@ -10842,7 +10843,7 @@ F: arch/mips/ F: drivers/platform/mips/ MIPS BOSTON DEVELOPMENT BOARD -M: Paul Burton +M: Paul Burton L: linux-mips@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/clock/img,boston-clock.txt @@ -10852,7 +10853,7 @@ F: drivers/clk/imgtec/clk-boston.c F: include/dt-bindings/clock/boston-clock.h MIPS GENERIC PLATFORM -M: Paul Burton +M: Paul Burton L: linux-mips@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/power/mti,mips-cpc.txt @@ -11407,7 +11408,6 @@ F: include/trace/events/tcp.h NETWORKING [TLS] M: Boris Pismenny M: Aviad Yehezkel -M: Dave Watson M: John Fastabend M: Daniel Borkmann M: Jakub Kicinski @@ -12312,12 +12312,15 @@ F: arch/parisc/ F: Documentation/parisc/ F: drivers/parisc/ F: drivers/char/agp/parisc-agp.c +F: drivers/input/misc/hp_sdc_rtc.c F: drivers/input/serio/gscps2.c +F: drivers/input/serio/hp_sdc* F: drivers/parport/parport_gsc.* F: drivers/tty/serial/8250/8250_gsc.c F: drivers/video/fbdev/sti* F: drivers/video/console/sti* F: drivers/video/logo/logo_parisc* +F: include/linux/hp_sdc.h PARMAN M: Jiri Pirko @@ -13361,7 +13364,7 @@ S: Maintained F: drivers/scsi/qla1280.[ch] QLOGIC QLA2XXX FC-SCSI DRIVER -M: qla2xxx-upstream@qlogic.com +M: hmadhani@marvell.com L: linux-scsi@vger.kernel.org S: Supported F: Documentation/scsi/LICENSE.qla2xxx @@ -13902,7 +13905,7 @@ F: drivers/mtd/nand/raw/r852.h RISC-V ARCHITECTURE M: Paul Walmsley -M: Palmer Dabbelt +M: Palmer Dabbelt M: Albert Ou L: linux-riscv@lists.infradead.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git @@ -14779,7 +14782,7 @@ F: drivers/media/usb/siano/ F: drivers/media/mmc/siano/ SIFIVE DRIVERS -M: Palmer Dabbelt +M: Palmer Dabbelt M: Paul Walmsley L: linux-riscv@lists.infradead.org T: git git://github.com/sifive/riscv-linux.git @@ -14789,7 +14792,7 @@ N: sifive SIFIVE FU540 SYSTEM-ON-CHIP M: Paul Walmsley -M: Palmer Dabbelt +M: Palmer Dabbelt L: linux-riscv@lists.infradead.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/pjw/sifive.git S: Supported @@ -17430,7 +17433,7 @@ F: include/linux/regulator/ K: regulator_get_optional VRF -M: David Ahern +M: David Ahern M: Shrijeet Mukherjee L: netdev@vger.kernel.org S: Maintained diff --git a/Makefile b/Makefile index 2e3ff166b80844c258f7255864a75ebfbe3e808b..5c12a389d472cf95dd66f450aeb25b864d1f5a1a 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ VERSION = 5 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -rc3 -NAME = Nesting Opossum +EXTRAVERSION = -rc6 +NAME = Kleptomaniac Octopus # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -1047,7 +1047,7 @@ export KBUILD_VMLINUX_OBJS := $(head-y) $(init-y) $(core-y) $(libs-y2) \ export KBUILD_VMLINUX_LIBS := $(libs-y1) export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds export LDFLAGS_vmlinux -# used by scripts/package/Makefile +# used by scripts/Makefile.package export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) LICENSES arch include scripts tools) vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7012373fe98dac62b32fe6790d31c3c85d7f0505 --- /dev/null +++ b/README.md @@ -0,0 +1,142 @@ +# How do I submit patches to Android Common Kernels + +1. BEST: Make all of your changes to upstream Linux. If appropriate, backport to the stable releases. + These patches will be merged automatically in the corresponding common kernels. If the patch is already + in upstream Linux, post a backport of the patch that conforms to the patch requirements below. + +2. LESS GOOD: Develop your patches out-of-tree (from an upstream Linux point-of-view). Unless these are + fixing an Android-specific bug, these are very unlikely to be accepted unless they have been + coordinated with kernel-team@android.com. If you want to proceed, post a patch that conforms to the + patch requirements below. + +# Common Kernel patch requirements + +- All patches must conform to the Linux kernel coding standards and pass `script/checkpatch.pl` +- Patches shall not break gki_defconfig or allmodconfig builds for arm, arm64, x86, x86_64 architectures +(see https://source.android.com/setup/build/building-kernels) +- If the patch is not merged from an upstream branch, the subject must be tagged with the type of patch: +`UPSTREAM:`, `BACKPORT:`, `FROMGIT:`, `FROMLIST:`, or `ANDROID:`. +- All patches must have a `Change-Id:` tag (see https://gerrit-review.googlesource.com/Documentation/user-changeid.html) +- If an Android bug has been assigned, there must be a `Bug:` tag. +- All patches must have a `Signed-off-by:` tag by the author and the submitter + +Additional requirements are listed below based on patch type + +## Requirements for backports from mainline Linux: `UPSTREAM:`, `BACKPORT:` + +- If the patch is a cherry-pick from Linux mainline with no changes at all + - tag the patch subject with `UPSTREAM:`. + - add upstream commit information with a `(cherry-picked from ...)` line + - Example: + - if the upstream commit message is +``` + important patch from upstream + + This is the detailed description of the important patch + + Signed-off-by: Fred Jones +``` + - then Joe Smith would upload the patch for the common kernel as +``` + UPSTREAM: important patch from upstream + + This is the detailed description of the important patch + + Signed-off-by: Fred Jones + + Bug: 135791357 + Change-Id: I4caaaa566ea080fa148c5e768bb1a0b6f7201c01 + (cherry-picked from c31e73121f4c1ec41143423ac6ce3ce6dafdcec1) + Signed-off-by: Joe Smith +``` + +- If the patch requires any changes from the upstream version, tag the patch with `BACKPORT:` +instead of `UPSTREAM:`. + - use the same tags as `UPSTREAM:` + - add comments about the changes under the `(cherry-picked from ...)` line + - Example: +``` + BACKPORT: important patch from upstream + + This is the detailed description of the important patch + + Signed-off-by: Fred Jones + + Bug: 135791357 + Change-Id: I4caaaa566ea080fa148c5e768bb1a0b6f7201c01 + (cherry-picked from c31e73121f4c1ec41143423ac6ce3ce6dafdcec1) + [ Resolved minor conflict in drivers/foo/bar.c ] + Signed-off-by: Joe Smith +``` + +## Requirements for other backports: `FROMGIT:`, `FROMLIST:`, + +- If the patch has been merged into an upstream maintainer tree, but has not yet +been merged into Linux mainline + - tag the patch subject with `FROMGIT:` + - add info on where the patch came from as `(cherry picked from commit )`. This +must be a stable maintainer branch (not rebased, so don't use `linux-next` for example). + - if changes were required, use `BACKPORT: FROMGIT:` + - Example: + - if the commit message in the maintainer tree is +``` + important patch from upstream + + This is the detailed description of the important patch + + Signed-off-by: Fred Jones +``` + - then Joe Smith would upload the patch for the common kernel as +``` + FROMGIT: important patch from upstream + + This is the detailed description of the important patch + + Signed-off-by: Fred Jones + + Bug: 135791357 + (cherry picked from commit 878a2fd9de10b03d11d2f622250285c7e63deace + https://git.kernel.org/pub/scm/linux/kernel/git/foo/bar.git test-branch) + Change-Id: I4caaaa566ea080fa148c5e768bb1a0b6f7201c01 + Signed-off-by: Joe Smith +``` + + +- If the patch has been submitted to LKML, but not accepted into any maintainer tree + - tag the patch subject with `FROMLIST:` + - add a `Link:` tag with a link to the submittal on lore.kernel.org + - if changes were required, use `BACKPORT: FROMLIST:` + - Example: +``` + FROMLIST: important patch from upstream + + This is the detailed description of the important patch + + Signed-off-by: Fred Jones + + Bug: 135791357 + Link: https://lore.kernel.org/lkml/20190619171517.GA17557@someone.com/ + Change-Id: I4caaaa566ea080fa148c5e768bb1a0b6f7201c01 + Signed-off-by: Joe Smith +``` + +## Requirements for Android-specific patches: `ANDROID:` + +- If the patch is fixing a bug to Android-specific code + - tag the patch subject with `ANDROID:` + - add a `Fixes:` tag that cites the patch with the bug + - Example: +``` + ANDROID: fix android-specific bug in foobar.c + + This is the detailed description of the important fix + + Fixes: 1234abcd2468 ("foobar: add cool feature") + Change-Id: I4caaaa566ea080fa148c5e768bb1a0b6f7201c01 + Signed-off-by: Joe Smith +``` + +- If the patch is a new feature + - tag the patch subject with `ANDROID:` + - add a `Bug:` tag with the Android bug (required for android-specific features) + diff --git a/arch/arc/boot/dts/hsdk.dts b/arch/arc/boot/dts/hsdk.dts index bfc7f5f5d6f26907121ddc20c4782a5d73f50265..9acbeba832c0b532ca1c4a2623f215335edcd481 100644 --- a/arch/arc/boot/dts/hsdk.dts +++ b/arch/arc/boot/dts/hsdk.dts @@ -65,6 +65,14 @@ clock-frequency = <33333333>; }; + reg_5v0: regulator-5v0 { + compatible = "regulator-fixed"; + + regulator-name = "5v0-supply"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + cpu_intc: cpu-interrupt-controller { compatible = "snps,archs-intc"; interrupt-controller; @@ -264,6 +272,21 @@ clocks = <&input_clk>; cs-gpios = <&creg_gpio 0 GPIO_ACTIVE_LOW>, <&creg_gpio 1 GPIO_ACTIVE_LOW>; + + spi-flash@0 { + compatible = "sst26wf016b", "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <4000000>; + }; + + adc@1 { + compatible = "ti,adc108s102"; + reg = <1>; + vref-supply = <®_5v0>; + spi-max-frequency = <1000000>; + }; }; creg_gpio: gpio@14b0 { diff --git a/arch/arc/configs/hsdk_defconfig b/arch/arc/configs/hsdk_defconfig index 9b9a74444ce27455dd5f403e476de3b78d771a23..0974226fab550ff384d59c8514fcb79139e7c1d4 100644 --- a/arch/arc/configs/hsdk_defconfig +++ b/arch/arc/configs/hsdk_defconfig @@ -32,6 +32,8 @@ CONFIG_INET=y CONFIG_DEVTMPFS=y # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_MTD=y +CONFIG_MTD_SPI_NOR=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_NETDEVICES=y @@ -55,6 +57,8 @@ CONFIG_GPIO_SYSFS=y CONFIG_GPIO_DWAPB=y CONFIG_GPIO_SNPS_CREG=y # CONFIG_HWMON is not set +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_DRM=y # CONFIG_DRM_FBDEV_EMULATION is not set CONFIG_DRM_UDL=y @@ -72,6 +76,8 @@ CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_DW=y CONFIG_DMADEVICES=y CONFIG_DW_AXI_DMAC=y +CONFIG_IIO=y +CONFIG_TI_ADC108S102=y CONFIG_EXT3_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index 861a8aea51f9fe0c086665dd84677f7ee80ea838..661fd842ea97db7ad4f3871b2a1038d715a44130 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -614,8 +614,8 @@ static int arc_pmu_device_probe(struct platform_device *pdev) /* loop thru all available h/w condition indexes */ for (i = 0; i < cc_bcr.c; i++) { write_aux_reg(ARC_REG_CC_INDEX, i); - cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0); - cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1); + cc_name.indiv.word0 = le32_to_cpu(read_aux_reg(ARC_REG_CC_NAME0)); + cc_name.indiv.word1 = le32_to_cpu(read_aux_reg(ARC_REG_CC_NAME1)); arc_pmu_map_hw_event(i, cc_name.str); arc_pmu_add_raw_event_attr(i, cc_name.str); diff --git a/arch/arm/boot/dts/am3874-iceboard.dts b/arch/arm/boot/dts/am3874-iceboard.dts index 883fb85135d4645ad449b4581080f1334942702f..1b4b2b0500e4c0214d8c057559dd3003bfedf13f 100644 --- a/arch/arm/boot/dts/am3874-iceboard.dts +++ b/arch/arm/boot/dts/am3874-iceboard.dts @@ -111,13 +111,13 @@ reg = <0x70>; #address-cells = <1>; #size-cells = <0>; + i2c-mux-idle-disconnect; i2c@0 { /* FMC A */ #address-cells = <1>; #size-cells = <0>; reg = <0>; - i2c-mux-idle-disconnect; }; i2c@1 { @@ -125,7 +125,6 @@ #address-cells = <1>; #size-cells = <0>; reg = <1>; - i2c-mux-idle-disconnect; }; i2c@2 { @@ -133,7 +132,6 @@ #address-cells = <1>; #size-cells = <0>; reg = <2>; - i2c-mux-idle-disconnect; }; i2c@3 { @@ -141,7 +139,6 @@ #address-cells = <1>; #size-cells = <0>; reg = <3>; - i2c-mux-idle-disconnect; }; i2c@4 { @@ -149,14 +146,12 @@ #address-cells = <1>; #size-cells = <0>; reg = <4>; - i2c-mux-idle-disconnect; }; i2c@5 { #address-cells = <1>; #size-cells = <0>; reg = <5>; - i2c-mux-idle-disconnect; ina230@40 { compatible = "ti,ina230"; reg = <0x40>; shunt-resistor = <5000>; }; ina230@41 { compatible = "ti,ina230"; reg = <0x41>; shunt-resistor = <5000>; }; @@ -182,14 +177,12 @@ #address-cells = <1>; #size-cells = <0>; reg = <6>; - i2c-mux-idle-disconnect; }; i2c@7 { #address-cells = <1>; #size-cells = <0>; reg = <7>; - i2c-mux-idle-disconnect; u41: pca9575@20 { compatible = "nxp,pca9575"; diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts index 09a088f98566178bbb4d5df30f44d03ca7280357..b75af21069f95d4b2bd4187d08cb2e974cbf6e5c 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts @@ -113,6 +113,7 @@ #address-cells = <1>; #size-cells = <0>; pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>; + bus-width = <4>; mmc-pwrseq = <&wifi_pwrseq>; non-removable; status = "okay"; diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi index 7c3cb7ece6cbf87c2f2e668fb7287968f95a44ee..925cb37c22f06b4f18e73f54b28bca45338c8b51 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi +++ b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi @@ -9,6 +9,14 @@ reg = <0 0x40000000>; }; + leds { + /* + * Since there is no upstream GPIO driver yet, + * remove the incomplete node. + */ + /delete-node/ act; + }; + reg_3v3: fixed-regulator { compatible = "regulator-fixed"; regulator-name = "3V3"; diff --git a/arch/arm/boot/dts/imx6-logicpd-som.dtsi b/arch/arm/boot/dts/imx6-logicpd-som.dtsi index 7ceae357324860c9ff79bf41c5deb34d6fff3cc1..547fb141ec0c9f4f2aace5f2095bfbd2d921d2dd 100644 --- a/arch/arm/boot/dts/imx6-logicpd-som.dtsi +++ b/arch/arm/boot/dts/imx6-logicpd-som.dtsi @@ -207,6 +207,10 @@ vin-supply = <&sw1c_reg>; }; +&snvs_poweroff { + status = "okay"; +}; + &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 710f850e785c6cbb465faa1697e15a52de378171..e2e604d6ba0b452d328a9488e956fffddd543c01 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -448,7 +448,7 @@ compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x302d0000 0x10000>; interrupts = ; - clocks = <&clks IMX7D_CLK_DUMMY>, + clocks = <&clks IMX7D_GPT1_ROOT_CLK>, <&clks IMX7D_GPT1_ROOT_CLK>; clock-names = "ipg", "per"; }; @@ -457,7 +457,7 @@ compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x302e0000 0x10000>; interrupts = ; - clocks = <&clks IMX7D_CLK_DUMMY>, + clocks = <&clks IMX7D_GPT2_ROOT_CLK>, <&clks IMX7D_GPT2_ROOT_CLK>; clock-names = "ipg", "per"; status = "disabled"; @@ -467,7 +467,7 @@ compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x302f0000 0x10000>; interrupts = ; - clocks = <&clks IMX7D_CLK_DUMMY>, + clocks = <&clks IMX7D_GPT3_ROOT_CLK>, <&clks IMX7D_GPT3_ROOT_CLK>; clock-names = "ipg", "per"; status = "disabled"; @@ -477,7 +477,7 @@ compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt"; reg = <0x30300000 0x10000>; interrupts = ; - clocks = <&clks IMX7D_CLK_DUMMY>, + clocks = <&clks IMX7D_GPT4_ROOT_CLK>, <&clks IMX7D_GPT4_ROOT_CLK>; clock-names = "ipg", "per"; status = "disabled"; diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi index 3fdd0a72f87f795b43d049a262ae5e3d7df2b967..506b118e511a6705007b4fe3decdcb8656eb65f2 100644 --- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi +++ b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi @@ -192,3 +192,7 @@ &twl_gpio { ti,use-leds; }; + +&twl_keypad { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/mt7629-rfb.dts b/arch/arm/boot/dts/mt7629-rfb.dts index 3621b7d2b22ac28eb905e5aa58e9ac0918c42eb5..9980c10c6e295f5e22dfaa3af94dd2b8c09f4f46 100644 --- a/arch/arm/boot/dts/mt7629-rfb.dts +++ b/arch/arm/boot/dts/mt7629-rfb.dts @@ -66,9 +66,21 @@ pinctrl-1 = <&ephy_leds_pins>; status = "okay"; + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + gmac1: mac@1 { compatible = "mediatek,eth-mac"; reg = <1>; + phy-mode = "gmii"; phy-handle = <&phy0>; }; @@ -78,7 +90,6 @@ phy0: ethernet-phy@0 { reg = <0>; - phy-mode = "gmii"; }; }; }; diff --git a/arch/arm/boot/dts/mt7629.dtsi b/arch/arm/boot/dts/mt7629.dtsi index 9608bc2ccb3f9367f0bf5172564f0dd761555c26..867b88103b9d6dc70cca6a274dbcd1e6ad5f9751 100644 --- a/arch/arm/boot/dts/mt7629.dtsi +++ b/arch/arm/boot/dts/mt7629.dtsi @@ -468,14 +468,12 @@ compatible = "mediatek,mt7629-sgmiisys", "syscon"; reg = <0x1b128000 0x3000>; #clock-cells = <1>; - mediatek,physpeed = "2500"; }; sgmiisys1: syscon@1b130000 { compatible = "mediatek,mt7629-sgmiisys", "syscon"; reg = <0x1b130000 0x3000>; #clock-cells = <1>; - mediatek,physpeed = "2500"; }; }; }; diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts index 4454449de00c0a784ad2b1a55e5238408ed32902..a40fe8d49da6469a573b43d1b0fa8e7d3ae08ada 100644 --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts @@ -369,7 +369,7 @@ compatible = "ti,wl1285", "ti,wl1283"; reg = <2>; /* gpio_100 with gpmc_wait2 pad as wakeirq */ - interrupts-extended = <&gpio4 4 IRQ_TYPE_EDGE_RISING>, + interrupts-extended = <&gpio4 4 IRQ_TYPE_LEVEL_HIGH>, <&omap4_pmx_core 0x4e>; interrupt-names = "irq", "wakeup"; ref-clock-frequency = <26000000>; diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi index 14be2ecb62b1f311aba87ad3e2dfd2b1b39ab834..55ea8b6189af56aa6956fc24306b90339a2fcb9a 100644 --- a/arch/arm/boot/dts/omap4-panda-common.dtsi +++ b/arch/arm/boot/dts/omap4-panda-common.dtsi @@ -474,7 +474,7 @@ compatible = "ti,wl1271"; reg = <2>; /* gpio_53 with gpmc_ncs3 pad as wakeup */ - interrupts-extended = <&gpio2 21 IRQ_TYPE_EDGE_RISING>, + interrupts-extended = <&gpio2 21 IRQ_TYPE_LEVEL_HIGH>, <&omap4_pmx_core 0x3a>; interrupt-names = "irq", "wakeup"; ref-clock-frequency = <38400000>; diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 3c274965ff40a24ab6aa3439c6b7f344b6d37757..91480ac1f32867bda4a26f0f61d81fe36b5ff29f 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -512,7 +512,7 @@ compatible = "ti,wl1281"; reg = <2>; interrupt-parent = <&gpio1>; - interrupts = <21 IRQ_TYPE_EDGE_RISING>; /* gpio 53 */ + interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 53 */ ref-clock-frequency = <26000000>; tcxo-clock-frequency = <26000000>; }; diff --git a/arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi b/arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi index 6dbbc9b3229cc0eec363a96754cddf371638138c..d0032213101e652dd4b7ce54615178ce5bf44e98 100644 --- a/arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi +++ b/arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi @@ -69,7 +69,7 @@ compatible = "ti,wl1271"; reg = <2>; interrupt-parent = <&gpio2>; - interrupts = <9 IRQ_TYPE_EDGE_RISING>; /* gpio 41 */ + interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; /* gpio 41 */ ref-clock-frequency = <38400000>; }; }; diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi index 7fff555ee39435435ed1f023648b8b36a6af4dd1..68ac04641bdb10ef8a5af855cba5234fecb33a7c 100644 --- a/arch/arm/boot/dts/omap5-board-common.dtsi +++ b/arch/arm/boot/dts/omap5-board-common.dtsi @@ -362,7 +362,7 @@ pinctrl-names = "default"; pinctrl-0 = <&wlcore_irq_pin>; interrupt-parent = <&gpio1>; - interrupts = <14 IRQ_TYPE_EDGE_RISING>; /* gpio 14 */ + interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; /* gpio 14 */ ref-clock-frequency = <26000000>; }; }; diff --git a/arch/arm/boot/dts/omap54xx-clocks.dtsi b/arch/arm/boot/dts/omap54xx-clocks.dtsi index fac2e57dcca905e6dd8af4bebcb57d89aa727805..4791834dacb2ef1814c195a85912941d8a28123e 100644 --- a/arch/arm/boot/dts/omap54xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap54xx-clocks.dtsi @@ -1146,7 +1146,7 @@ }; }; - gpu_cm: clock-controller@1500 { + gpu_cm: gpu_cm@1500 { compatible = "ti,omap4-cm"; reg = <0x1500 0x100>; #address-cells = <1>; diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi index e4a0d51ec3a8cde7003099dcc29f008f82704e74..0a3a7d66737b60dd4f3ff991e5ffc68629660e4b 100644 --- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi @@ -609,13 +609,13 @@ ; /* QSPI_BK1_IO3 */ bias-disable; drive-push-pull; - slew-rate = <3>; + slew-rate = <1>; }; pins2 { pinmux = ; /* QSPI_BK1_NCS */ bias-pull-up; drive-push-pull; - slew-rate = <3>; + slew-rate = <1>; }; }; @@ -637,13 +637,13 @@ ; /* QSPI_BK2_IO3 */ bias-disable; drive-push-pull; - slew-rate = <3>; + slew-rate = <1>; }; pins2 { pinmux = ; /* QSPI_BK2_NCS */ bias-pull-up; drive-push-pull; - slew-rate = <3>; + slew-rate = <1>; }; }; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 874231be04e4608a8e6fb337a06e3ae6719e1af3..8aebefd6accfee08a67dd7a12ecb41a7576f470d 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -380,9 +380,8 @@ compatible = "allwinner,sun7i-a20-csi0"; reg = <0x01c09000 0x1000>; interrupts = ; - clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>, - <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>; - clock-names = "bus", "mod", "isp", "ram"; + clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>; + clock-names = "bus", "isp", "ram"; resets = <&ccu RST_CSI0>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts index dc8a5f37a1ef2a6029bfcbd1d77e46d4b1936a7c..c8ebb23c4e02b03c2401db216d990ec3d63dd3d7 100644 --- a/arch/arm/boot/dts/vf610-zii-scu4-aib.dts +++ b/arch/arm/boot/dts/vf610-zii-scu4-aib.dts @@ -602,6 +602,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x70>; + i2c-mux-idle-disconnect; sff0_i2c: i2c@1 { #address-cells = <1>; @@ -640,6 +641,7 @@ reg = <0x71>; #address-cells = <1>; #size-cells = <0>; + i2c-mux-idle-disconnect; sff5_i2c: i2c@1 { #address-cells = <1>; diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig index 01e3c0f4be92341c4c8a9a499661b2181d902a05..231f8973bbb2d8ca242eef675b2c4fbed6ba554b 100644 --- a/arch/arm/configs/davinci_all_defconfig +++ b/arch/arm/configs/davinci_all_defconfig @@ -167,6 +167,7 @@ CONFIG_FB=y CONFIG_FIRMWARE_EDID=y CONFIG_FB_DA8XX=y CONFIG_BACKLIGHT_PWM=m +CONFIG_BACKLIGHT_GPIO=m CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y CONFIG_SOUND=m diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 9bfffbe22d53cd9732b98415477aa61bd97c430e..0f7381ee0c375ff16db8ab7efe57d12dc9b88cd7 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -276,6 +276,7 @@ CONFIG_VIDEO_OV5640=m CONFIG_VIDEO_OV5645=m CONFIG_IMX_IPUV3_CORE=y CONFIG_DRM=y +CONFIG_DRM_MSM=y CONFIG_DRM_PANEL_LVDS=y CONFIG_DRM_PANEL_SIMPLE=y CONFIG_DRM_PANEL_SEIKO_43WVF1G=y diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index d3f50971e451a4234da97cb09bcd05cf3fad60e1..40d7f1a4fc458b5b9b777cfaee99a995f2bddfac 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -356,15 +356,15 @@ CONFIG_DRM_OMAP_CONNECTOR_HDMI=m CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV=m CONFIG_DRM_OMAP_PANEL_DPI=m CONFIG_DRM_OMAP_PANEL_DSI_CM=m -CONFIG_DRM_OMAP_PANEL_SONY_ACX565AKM=m -CONFIG_DRM_OMAP_PANEL_LGPHILIPS_LB035Q02=m -CONFIG_DRM_OMAP_PANEL_SHARP_LS037V7DW01=m -CONFIG_DRM_OMAP_PANEL_TPO_TD028TTEC1=m -CONFIG_DRM_OMAP_PANEL_TPO_TD043MTEA1=m -CONFIG_DRM_OMAP_PANEL_NEC_NL8048HL11=m CONFIG_DRM_TILCDC=m CONFIG_DRM_PANEL_SIMPLE=m CONFIG_DRM_TI_TFP410=m +CONFIG_DRM_PANEL_LG_LB035Q02=m +CONFIG_DRM_PANEL_NEC_NL8048HL11=m +CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m +CONFIG_DRM_PANEL_SONY_ACX565AKM=m +CONFIG_DRM_PANEL_TPO_TD028TTEC1=m +CONFIG_DRM_PANEL_TPO_TD043MTEA1=m CONFIG_FB=y CONFIG_FIRMWARE_EDID=y CONFIG_FB_MODE_HELPERS=y diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index 567dbede4785ce96b89718cc9f1725150d13d4eb..f1d0a7807cd0e13beca85a00ea9a34ef504b104a 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h @@ -82,7 +82,7 @@ #ifndef __ASSEMBLY__ #ifdef CONFIG_CPU_CP15_MMU -static inline unsigned int get_domain(void) +static __always_inline unsigned int get_domain(void) { unsigned int domain; @@ -94,7 +94,7 @@ static inline unsigned int get_domain(void) return domain; } -static inline void set_domain(unsigned val) +static __always_inline void set_domain(unsigned int val) { asm volatile( "mcr p15, 0, %0, c3, c0 @ set domain" @@ -102,12 +102,12 @@ static inline void set_domain(unsigned val) isb(); } #else -static inline unsigned int get_domain(void) +static __always_inline unsigned int get_domain(void) { return 0; } -static inline void set_domain(unsigned val) +static __always_inline void set_domain(unsigned int val) { } #endif diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 303248e5b990f5ae4698432050aa53a6f0014340..98c6b91be4a8addd8212a3f170927e259ffb0e0d 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -22,7 +22,7 @@ * perform such accesses (eg, via list poison values) which could then * be exploited for priviledge escalation. */ -static inline unsigned int uaccess_save_and_enable(void) +static __always_inline unsigned int uaccess_save_and_enable(void) { #ifdef CONFIG_CPU_SW_DOMAIN_PAN unsigned int old_domain = get_domain(); @@ -37,7 +37,7 @@ static inline unsigned int uaccess_save_and_enable(void) #endif } -static inline void uaccess_restore(unsigned int flags) +static __always_inline void uaccess_restore(unsigned int flags) { #ifdef CONFIG_CPU_SW_DOMAIN_PAN /* Restore the user access mask */ diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index a7810be07da1c56c1502a72b60d7bc3da8075d91..4a3982812a401f1259909df4e1d05ead3f29dd9c 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -68,7 +68,7 @@ ENDPROC(__vet_atags) * The following fragment of code is executed with the MMU on in MMU mode, * and uses absolute addresses; this is not position independent. * - * r0 = cp#15 control register + * r0 = cp#15 control register (exc_ret for M-class) * r1 = machine ID * r2 = atags/dtb pointer * r9 = processor ID @@ -137,7 +137,8 @@ __mmap_switched_data: #ifdef CONFIG_CPU_CP15 .long cr_alignment @ r3 #else - .long 0 @ r3 +M_CLASS(.long exc_ret) @ r3 +AR_CLASS(.long 0) @ r3 #endif .size __mmap_switched_data, . - __mmap_switched_data diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index afa350f44dea3308609754e279e040c10c711f95..0fc814bbc34b171e43e55a57b081220b15fe70a2 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -201,6 +201,8 @@ M_CLASS(streq r3, [r12, #PMSAv8_MAIR1]) bic r0, r0, #V7M_SCB_CCR_IC #endif str r0, [r12, V7M_SCB_CCR] + /* Pass exc_ret to __mmap_switched */ + mov r0, r10 #endif /* CONFIG_CPU_CP15 elif CONFIG_CPU_V7M */ ret lr ENDPROC(__after_proc_init) diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 8062412be70f06dc8d252ca45f9f5ff86bba262e..9fc5c73cc0be2d0644036eaa9ed15b9083af7ea5 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -462,8 +462,8 @@ static s8 dm365_queue_priority_mapping[][2] = { }; static const struct dma_slave_map dm365_edma_map[] = { - { "davinci-mcbsp.0", "tx", EDMA_FILTER_PARAM(0, 2) }, - { "davinci-mcbsp.0", "rx", EDMA_FILTER_PARAM(0, 3) }, + { "davinci-mcbsp", "tx", EDMA_FILTER_PARAM(0, 2) }, + { "davinci-mcbsp", "rx", EDMA_FILTER_PARAM(0, 3) }, { "davinci_voicecodec", "tx", EDMA_FILTER_PARAM(0, 2) }, { "davinci_voicecodec", "rx", EDMA_FILTER_PARAM(0, 3) }, { "spi_davinci.2", "tx", EDMA_FILTER_PARAM(0, 10) }, diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index d942a335709076fe743935e3331d65388d270707..2efd18e8824c78e597eb28aa2332d85193660167 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -89,6 +89,13 @@ static struct iommu_platform_data omap3_iommu_pdata = { .reset_name = "mmu", .assert_reset = omap_device_assert_hardreset, .deassert_reset = omap_device_deassert_hardreset, + .device_enable = omap_device_enable, + .device_idle = omap_device_idle, +}; + +static struct iommu_platform_data omap3_iommu_isp_pdata = { + .device_enable = omap_device_enable, + .device_idle = omap_device_idle, }; static int omap3_sbc_t3730_twl_callback(struct device *dev, @@ -424,6 +431,8 @@ static struct iommu_platform_data omap4_iommu_pdata = { .reset_name = "mmu_cache", .assert_reset = omap_device_assert_hardreset, .deassert_reset = omap_device_deassert_hardreset, + .device_enable = omap_device_enable, + .device_idle = omap_device_idle, }; #endif @@ -617,6 +626,8 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = { #ifdef CONFIG_ARCH_OMAP3 OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu", &omap3_iommu_pdata), + OF_DEV_AUXDATA("ti,omap2-iommu", 0x480bd400, "480bd400.mmu", + &omap3_iommu_isp_pdata), OF_DEV_AUXDATA("ti,omap3-smartreflex-core", 0x480cb000, "480cb000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]), OF_DEV_AUXDATA("ti,omap3-smartreflex-mpu-iva", 0x480c9000, diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 04b36436cbc04877a060b10670bf453dd2ed0e2d..788c5cf46de593a8e53265c7de3842496fe21dc1 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -324,7 +324,7 @@ union offset_union { __put32_unaligned_check("strbt", val, addr) static void -do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs *regs, union offset_union offset) +do_alignment_finish_ldst(unsigned long addr, u32 instr, struct pt_regs *regs, union offset_union offset) { if (!LDST_U_BIT(instr)) offset.un = -offset.un; @@ -337,7 +337,7 @@ do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs } static int -do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs) +do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); @@ -386,8 +386,7 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r } static int -do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, - struct pt_regs *regs) +do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); unsigned int rd2; @@ -449,7 +448,7 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, } static int -do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *regs) +do_alignment_ldrstr(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); @@ -498,7 +497,7 @@ do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *reg * PU = 10 A B */ static int -do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *regs) +do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd, rn, correction, nr_regs, regbits; unsigned long eaddr, newaddr; @@ -539,7 +538,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg * processor for us. */ if (addr != eaddr) { - pr_err("LDMSTM: PC = %08lx, instr = %08lx, " + pr_err("LDMSTM: PC = %08lx, instr = %08x, " "addr = %08lx, eaddr = %08lx\n", instruction_pointer(regs), instr, addr, eaddr); show_regs(regs); @@ -716,10 +715,10 @@ thumb2arm(u16 tinstr) * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt) */ static void * -do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs, +do_alignment_t32_to_handler(u32 *pinstr, struct pt_regs *regs, union offset_union *poffset) { - unsigned long instr = *pinstr; + u32 instr = *pinstr; u16 tinst1 = (instr >> 16) & 0xffff; u16 tinst2 = instr & 0xffff; @@ -767,17 +766,48 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs, return NULL; } +static int alignment_get_arm(struct pt_regs *regs, u32 *ip, u32 *inst) +{ + u32 instr = 0; + int fault; + + if (user_mode(regs)) + fault = get_user(instr, ip); + else + fault = probe_kernel_address(ip, instr); + + *inst = __mem_to_opcode_arm(instr); + + return fault; +} + +static int alignment_get_thumb(struct pt_regs *regs, u16 *ip, u16 *inst) +{ + u16 instr = 0; + int fault; + + if (user_mode(regs)) + fault = get_user(instr, ip); + else + fault = probe_kernel_address(ip, instr); + + *inst = __mem_to_opcode_thumb16(instr); + + return fault; +} + static int do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { union offset_union uninitialized_var(offset); - unsigned long instr = 0, instrptr; - int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); + unsigned long instrptr; + int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs); unsigned int type; - unsigned int fault; + u32 instr = 0; u16 tinstr = 0; int isize = 4; int thumb2_32b = 0; + int fault; if (interrupts_enabled(regs)) local_irq_enable(); @@ -786,15 +816,14 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (thumb_mode(regs)) { u16 *ptr = (u16 *)(instrptr & ~1); - fault = probe_kernel_address(ptr, tinstr); - tinstr = __mem_to_opcode_thumb16(tinstr); + + fault = alignment_get_thumb(regs, ptr, &tinstr); if (!fault) { if (cpu_architecture() >= CPU_ARCH_ARMv7 && IS_T32(tinstr)) { /* Thumb-2 32-bit */ - u16 tinst2 = 0; - fault = probe_kernel_address(ptr + 1, tinst2); - tinst2 = __mem_to_opcode_thumb16(tinst2); + u16 tinst2; + fault = alignment_get_thumb(regs, ptr + 1, &tinst2); instr = __opcode_thumb32_compose(tinstr, tinst2); thumb2_32b = 1; } else { @@ -803,8 +832,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) } } } else { - fault = probe_kernel_address((void *)instrptr, instr); - instr = __mem_to_opcode_arm(instr); + fault = alignment_get_arm(regs, (void *)instrptr, &instr); } if (fault) { @@ -926,7 +954,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) * Oops, we didn't handle the instruction. */ pr_err("Alignment trap: not handling instruction " - "%0*lx at [<%08lx>]\n", + "%0*x at [<%08lx>]\n", isize << 1, isize == 2 ? tinstr : instr, instrptr); ai_skipped += 1; @@ -936,7 +964,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ai_user += 1; if (ai_usermode & UM_WARN) - printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx " + printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*x " "Address=0x%08lx FSR 0x%03x\n", current->comm, task_pid_nr(current), instrptr, isize << 1, diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S index 1448f144e7fb9c441902e2728f572aa91f405157..1a49d503eafc80b461d256f4f068e9a54c6d85f6 100644 --- a/arch/arm/mm/proc-v7m.S +++ b/arch/arm/mm/proc-v7m.S @@ -132,13 +132,11 @@ __v7m_setup_cont: dsb mov r6, lr @ save LR ldr sp, =init_thread_union + THREAD_START_SP - stmia sp, {r0-r3, r12} cpsie i svc #0 1: cpsid i - ldr r0, =exc_ret - orr lr, lr, #EXC_RET_THREADMODE_PROCESSSTACK - str lr, [r0] + /* Calculate exc_ret */ + orr r10, lr, #EXC_RET_THREADMODE_PROCESSSTACK ldmia sp, {r0-r3, r12} str r5, [r12, #11 * 4] @ restore the original SVC vector entry mov lr, r6 @ restore LR diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 1714ae982724f0d0a731390b7436aa8dc7586e0c..6fdfbae8c232a568f1b5994fe2934b9be78a7c48 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -618,6 +618,23 @@ config CAVIUM_ERRATUM_30115 If unsure, say Y. +config CAVIUM_TX2_ERRATUM_219 + bool "Cavium ThunderX2 erratum 219: PRFM between TTBR change and ISB fails" + default y + help + On Cavium ThunderX2, a load, store or prefetch instruction between a + TTBR update and the corresponding context synchronizing operation can + cause a spurious Data Abort to be delivered to any hardware thread in + the CPU core. + + Work around the issue by avoiding the problematic code sequence and + trapping KVM guest TTBRx_EL1 writes to EL2 when SMT is enabled. The + trap handler performs the corresponding register access, skips the + instruction and ensures context synchronization by virtue of the + exception return. + + If unsure, say Y. + config QCOM_FALKOR_ERRATUM_1003 bool "Falkor E1003: Incorrect translation due to ASID change" default y diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts index 24f1aac366d64355f5b6b37bb8e263bcce7f2e2d..d5b6e8159a335a0fde372e68f84e2101fc448560 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts @@ -63,3 +63,12 @@ reg = <1>; }; }; + +®_dc1sw { + /* + * Ethernet PHY needs 30ms to properly power up and some more + * to initialize. 100ms should be plenty of time to finish + * whole process. + */ + regulator-enable-ramp-delay = <100000>; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts index e6fb9683f21355ea7e3a947b20b3ea4fc7900d61..25099202c52c99d37b06ca3127dcc9b9b8214b4b 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts @@ -159,6 +159,12 @@ }; ®_dc1sw { + /* + * Ethernet PHY needs 30ms to properly power up and some more + * to initialize. 100ms should be plenty of time to finish + * whole process. + */ + regulator-enable-ramp-delay = <100000>; regulator-name = "vcc-phy"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 3eccbdba7154939e965e6f14faeeb5c8123ff64b..70f4cce6be43e1707aa5b0a3b682c281683d1857 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -142,15 +142,6 @@ clock-output-names = "ext-osc32k"; }; - pmu { - compatible = "arm,cortex-a53-pmu"; - interrupts = , - , - , - ; - interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; - }; - psci { compatible = "arm,psci-0.2"; method = "smc"; diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi index 8a3a770e8f2ce62bb99fc9fd74461073cfa7780a..56789ccf94545f39cde28c34f9dba8af495322a7 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi @@ -42,13 +42,14 @@ pinmux: pinmux@14029c { compatible = "pinctrl-single"; - reg = <0x0014029c 0x250>; + reg = <0x0014029c 0x26c>; #address-cells = <1>; #size-cells = <1>; pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xf>; pinctrl-single,gpio-range = < - &range 0 154 MODE_GPIO + &range 0 91 MODE_GPIO + &range 95 60 MODE_GPIO >; range: gpio-range { #pinctrl-single,gpio-range-cells = <3>; diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi index 71e2e34400d40dab63f864f347bb1203ec6873eb..0098dfdef96c0285db363155f0bdb72706193d1c 100644 --- a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi +++ b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi @@ -464,8 +464,7 @@ <&pinmux 108 16 27>, <&pinmux 135 77 6>, <&pinmux 141 67 4>, - <&pinmux 145 149 6>, - <&pinmux 151 91 4>; + <&pinmux 145 149 6>; }; i2c1: i2c@e0000 { diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi index 408e0ecdce6a5b2024fb89bed1cc7902dafb5180..b032f3890c8c61c0b4e8fa92e94ef57981a18118 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi @@ -33,7 +33,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster0_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@1 { @@ -49,7 +49,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster0_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@100 { @@ -65,7 +65,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster1_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@101 { @@ -81,7 +81,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster1_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@200 { @@ -97,7 +97,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster2_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@201 { @@ -113,7 +113,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster2_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@300 { @@ -129,7 +129,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster3_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@301 { @@ -145,7 +145,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster3_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@400 { @@ -161,7 +161,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster4_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@401 { @@ -177,7 +177,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster4_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@500 { @@ -193,7 +193,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster5_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@501 { @@ -209,7 +209,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster5_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@600 { @@ -225,7 +225,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster6_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@601 { @@ -241,7 +241,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster6_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@700 { @@ -257,7 +257,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster7_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cpu@701 { @@ -273,7 +273,7 @@ i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster7_l2>; - cpu-idle-states = <&cpu_pw20>; + cpu-idle-states = <&cpu_pw15>; }; cluster0_l2: l2-cache0 { @@ -340,9 +340,9 @@ cache-level = <2>; }; - cpu_pw20: cpu-pw20 { + cpu_pw15: cpu-pw15 { compatible = "arm,idle-state"; - idle-state-name = "PW20"; + idle-state-name = "PW15"; arm,psci-suspend-param = <0x0>; entry-latency-us = <2000>; exit-latency-us = <2000>; diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi index 5f9d0da196e13c695ccc340a2f5ab5bc96985f67..58b8cd06cae78e7866f8a3a2d4e3ba0617fa0834 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi @@ -694,7 +694,7 @@ compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b40000 0x10000>; interrupts = ; - clocks = <&clk IMX8MM_CLK_DUMMY>, + clocks = <&clk IMX8MM_CLK_IPG_ROOT>, <&clk IMX8MM_CLK_NAND_USDHC_BUS>, <&clk IMX8MM_CLK_USDHC1_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -710,7 +710,7 @@ compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b50000 0x10000>; interrupts = ; - clocks = <&clk IMX8MM_CLK_DUMMY>, + clocks = <&clk IMX8MM_CLK_IPG_ROOT>, <&clk IMX8MM_CLK_NAND_USDHC_BUS>, <&clk IMX8MM_CLK_USDHC2_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -724,7 +724,7 @@ compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b60000 0x10000>; interrupts = ; - clocks = <&clk IMX8MM_CLK_DUMMY>, + clocks = <&clk IMX8MM_CLK_IPG_ROOT>, <&clk IMX8MM_CLK_NAND_USDHC_BUS>, <&clk IMX8MM_CLK_USDHC3_ROOT>; clock-names = "ipg", "ahb", "per"; diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi index 785f4c420fa4c518dad3bc0e20ad4528279b96e7..98496f570720407369b0242897efd0fd5207214c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -569,7 +569,7 @@ compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b40000 0x10000>; interrupts = ; - clocks = <&clk IMX8MN_CLK_DUMMY>, + clocks = <&clk IMX8MN_CLK_IPG_ROOT>, <&clk IMX8MN_CLK_NAND_USDHC_BUS>, <&clk IMX8MN_CLK_USDHC1_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -585,7 +585,7 @@ compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b50000 0x10000>; interrupts = ; - clocks = <&clk IMX8MN_CLK_DUMMY>, + clocks = <&clk IMX8MN_CLK_IPG_ROOT>, <&clk IMX8MN_CLK_NAND_USDHC_BUS>, <&clk IMX8MN_CLK_USDHC2_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -599,7 +599,7 @@ compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc"; reg = <0x30b60000 0x10000>; interrupts = ; - clocks = <&clk IMX8MN_CLK_DUMMY>, + clocks = <&clk IMX8MN_CLK_IPG_ROOT>, <&clk IMX8MN_CLK_NAND_USDHC_BUS>, <&clk IMX8MN_CLK_USDHC3_ROOT>; clock-names = "ipg", "ahb", "per"; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi index af99473ada04377fd32af9304f5eeac8d74b1fba..087b5b6ebe8906f932b827ca1d5261cf78c4427b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi @@ -89,8 +89,8 @@ regulator-min-microvolt = <900000>; regulator-max-microvolt = <1000000>; gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; - states = <1000000 0x0 - 900000 0x1>; + states = <1000000 0x1 + 900000 0x0>; regulator-always-on; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index 04115ca6bfb528c40a7f7cf207c57d2377c1a1ba..55a3d1c4bdf04cfc8df24adc230d23a0702c0180 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -850,7 +850,7 @@ "fsl,imx7d-usdhc"; reg = <0x30b40000 0x10000>; interrupts = ; - clocks = <&clk IMX8MQ_CLK_DUMMY>, + clocks = <&clk IMX8MQ_CLK_IPG_ROOT>, <&clk IMX8MQ_CLK_NAND_USDHC_BUS>, <&clk IMX8MQ_CLK_USDHC1_ROOT>; clock-names = "ipg", "ahb", "per"; @@ -867,7 +867,7 @@ "fsl,imx7d-usdhc"; reg = <0x30b50000 0x10000>; interrupts = ; - clocks = <&clk IMX8MQ_CLK_DUMMY>, + clocks = <&clk IMX8MQ_CLK_IPG_ROOT>, <&clk IMX8MQ_CLK_NAND_USDHC_BUS>, <&clk IMX8MQ_CLK_USDHC2_ROOT>; clock-names = "ipg", "ahb", "per"; diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts index d105986c6be1a6f0a63f511b2bcd8c1d24fc1d3e..5f350cc71a2fdb08e1e7c589ef8d51267b82576f 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts @@ -60,11 +60,6 @@ gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>; }; - usb3_phy: usb3-phy { - compatible = "usb-nop-xceiv"; - vcc-supply = <&exp_usb3_vbus>; - }; - vsdc_reg: vsdc-reg { compatible = "regulator-gpio"; regulator-name = "vsdc"; @@ -255,10 +250,16 @@ status = "okay"; }; +&comphy2 { + connector { + compatible = "usb-a-connector"; + phy-supply = <&exp_usb3_vbus>; + }; +}; + &usb3 { status = "okay"; phys = <&comphy2 0>; - usb-phy = <&usb3_phy>; }; &mdio { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts index e152b0ca0290c7f69e86f6b3c96a7ed16c5e3091..b8066868a3fe6ba79354040e20770e7c1c62a826 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts @@ -44,7 +44,7 @@ power-supply = <&pp3300_disp>; panel-timing { - clock-frequency = <266604720>; + clock-frequency = <266666667>; hactive = <2400>; hfront-porch = <48>; hback-porch = <84>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts index 0d1f5f9a0de9558733446b2f9dec48ca12e58501..c133e8d64b2a3d2dfac63fedb401657ae7b7f380 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts @@ -644,7 +644,7 @@ status = "okay"; u2phy0_host: host-port { - phy-supply = <&vcc5v0_host>; + phy-supply = <&vcc5v0_typec>; status = "okay"; }; @@ -712,7 +712,7 @@ &usbdrd_dwc3_0 { status = "okay"; - dr_mode = "otg"; + dr_mode = "host"; }; &usbdrd3_1 { diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts index 0401d4ec1f4527067485d864b183fb6103962624..e544deb61d288285610a2d28aea8ecf1a40adc17 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts @@ -173,7 +173,7 @@ regulator-always-on; regulator-boot-on; regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1400000>; + regulator-max-microvolt = <1700000>; vin-supply = <&vcc5v0_sys>; }; }; @@ -247,8 +247,8 @@ rk808: pmic@1b { compatible = "rockchip,rk808"; reg = <0x1b>; - interrupt-parent = <&gpio1>; - interrupts = <21 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&gpio3>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; #clock-cells = <1>; clock-output-names = "xin32k", "rk808-clkout2"; pinctrl-names = "default"; @@ -574,7 +574,7 @@ pmic { pmic_int_l: pmic-int-l { - rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; }; vsel1_gpio: vsel1-gpio { @@ -624,7 +624,6 @@ &sdmmc { bus-width = <4>; - cap-mmc-highspeed; cap-sd-highspeed; cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; disable-wp; @@ -636,8 +635,7 @@ &sdhci { bus-width = <8>; - mmc-hs400-1_8v; - mmc-hs400-enhanced-strobe; + mmc-hs200-1_8v; non-removable; status = "okay"; }; diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index 80ebf75319a1f6c5953e75b92c1d8cfffe9daa86..441e6228082f5cea13a7794778c3ae8ad10026ea 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -61,6 +61,7 @@ CONFIG_CPU_FREQ_TIMES=y CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPUFREQ_DUMMY=m CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_ARM_SCMI_CPUFREQ=y CONFIG_ARM_SCMI_PROTOCOL=y @@ -75,6 +76,7 @@ CONFIG_KPROBES=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_GKI_HACKS_TO_FIX=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_MEMORY_HOTPLUG=y @@ -213,6 +215,7 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SCSI_UFSHCD=y CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_CRYPTO=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y @@ -260,6 +263,7 @@ CONFIG_USB_USBNET=y # CONFIG_WLAN_VENDOR_QUANTENNA is not set CONFIG_VIRT_WIFI=y CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y CONFIG_INPUT_MISC=y @@ -284,6 +288,7 @@ CONFIG_HW_RANDOM_VIRTIO=y # CONFIG_I2C_HELPER_AUTO is not set CONFIG_SPI=y CONFIG_SPMI=y +# CONFIG_SPMI_MSM_PMIC_ARB is not set CONFIG_PINCTRL_AMD=y CONFIG_POWER_AVS=y CONFIG_POWER_RESET_HISI=y @@ -296,7 +301,6 @@ CONFIG_WATCHDOG=y CONFIG_MFD_ACT8945A=y CONFIG_MFD_SYSCON=y CONFIG_REGULATOR=y -CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_CONTROLLER=y # CONFIG_VGA_ARB is not set @@ -381,6 +385,7 @@ CONFIG_EXT4_FS_SECURITY=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_FS_VERITY=y CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y # CONFIG_DNOTIFY is not set @@ -449,6 +454,7 @@ CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_HARDENED_USERCOPY=y +CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_CRYPTO_ADIANTUM=y CONFIG_CRYPTO_MD4=y diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h index f74909ba29bdd30ca420be3f98acd72a2113a2cd..5bf963830b173151f4e2983ecb4481848917c85b 100644 --- a/arch/arm64/include/asm/asm-uaccess.h +++ b/arch/arm64/include/asm/asm-uaccess.h @@ -78,10 +78,9 @@ alternative_else_nop_endif /* * Remove the address tag from a virtual address, if present. */ - .macro clear_address_tag, dst, addr - tst \addr, #(1 << 55) - bic \dst, \addr, #(0xff << 56) - csel \dst, \dst, \addr, eq + .macro untagged_addr, dst, addr + sbfx \dst, \addr, #0, #56 + and \dst, \dst, \addr .endm #endif diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index f19fe4b9acc4d148c6e9ebb535be0b03e6f9b352..ac1dbca3d0cd3db0dc5396d05d38eb7dfb679da0 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -52,7 +52,9 @@ #define ARM64_HAS_IRQ_PRIO_MASKING 42 #define ARM64_HAS_DCPODP 43 #define ARM64_WORKAROUND_1463225 44 +#define ARM64_WORKAROUND_CAVIUM_TX2_219_TVM 45 +#define ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM 46 -#define ARM64_NCAPS 45 +#define ARM64_NCAPS 47 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index b1454d117cd2c69582d519f123fcaa66f5f81c44..aca07c2f6e6e364e84efb9708f8a743cf24e6627 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -79,6 +79,7 @@ #define CAVIUM_CPU_PART_THUNDERX_83XX 0x0A3 #define CAVIUM_CPU_PART_THUNDERX2 0x0AF +#define BRCM_CPU_PART_BRAHMA_B53 0x100 #define BRCM_CPU_PART_VULCAN 0x516 #define QCOM_CPU_PART_FALKOR_V1 0x800 @@ -105,6 +106,7 @@ #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) #define MIDR_CAVIUM_THUNDERX2 MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX2) +#define MIDR_BRAHMA_B53 MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_BRAHMA_B53) #define MIDR_BRCM_VULCAN MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN) #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1) #define MIDR_QCOM_FALKOR MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR) diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index b61b50bf68b1893024e997d268fbbb3c91153d91..c23c473606647521673ee7b2274a249d1688f125 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -215,12 +215,18 @@ static inline unsigned long kaslr_offset(void) * up with a tagged userland pointer. Clear the tag to get a sane pointer to * pass on to access_ok(), for instance. */ -#define untagged_addr(addr) \ +#define __untagged_addr(addr) \ ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55)) +#define untagged_addr(addr) ({ \ + u64 __addr = (__force u64)addr; \ + __addr &= __untagged_addr(__addr); \ + (__force __typeof__(addr))__addr; \ +}) + #ifdef CONFIG_KASAN_SW_TAGS #define __tag_shifted(tag) ((u64)(tag) << 56) -#define __tag_reset(addr) untagged_addr(addr) +#define __tag_reset(addr) __untagged_addr(addr) #define __tag_get(addr) (__u8)((u64)(addr) >> 56) #else #define __tag_shifted(tag) 0UL diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index 9a21b84536f2e04bdf0698e20dc52aa81d952783..8dc6c5cdabe62e2f63065abd525ff516fe685387 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -32,11 +32,11 @@ #define PROT_DEFAULT (_PROT_DEFAULT | PTE_MAYBE_NG) #define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_MAYBE_NG) -#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) -#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) -#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC)) -#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT)) -#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) +#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) +#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) +#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC)) +#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT)) +#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) #define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) @@ -80,8 +80,9 @@ #define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_S2_XN) #define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) -#define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) -#define PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE) +/* shared+writable pages are clean by default, hence PTE_RDONLY|PTE_WRITE */ +#define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) +#define PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE) #define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) #define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN) #define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 7576df00eb50e8f7109d711846f758369a50eb85..8330810f699e31bd01794f8dc5ad17dd419646f6 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -876,9 +876,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0) -#define kc_vaddr_to_offset(v) ((v) & ~PAGE_END) -#define kc_offset_to_vaddr(o) ((o) | PAGE_END) - #ifdef CONFIG_ARM64_PA_BITS_52 #define phys_to_ttbr(addr) (((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52) #else diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 972d196c7714689ab46d22b6366453b7e018c721..6e919fafb43dd65b407a3ec537408b240319ce7d 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -212,7 +212,7 @@ #define SYS_FAR_EL1 sys_reg(3, 0, 6, 0, 0) #define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0) -#define SYS_PAR_EL1_F BIT(1) +#define SYS_PAR_EL1_F BIT(0) #define SYS_PAR_EL1_FST GENMASK(6, 1) /*** Statistical Profiling Extension ***/ diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f593f4cffc0dd49a04301a66646863b4d6f9f281..93f34b4eca2547413c8d49e8a4e735fcac403ba3 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -12,6 +12,7 @@ #include #include #include +#include static bool __maybe_unused is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope) @@ -488,6 +489,7 @@ static const struct midr_range arm64_ssb_cpus[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A35), MIDR_ALL_VERSIONS(MIDR_CORTEX_A53), MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), + MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), {}, }; @@ -572,6 +574,7 @@ static const struct midr_range spectre_v2_safe_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A35), MIDR_ALL_VERSIONS(MIDR_CORTEX_A53), MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), + MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), { /* sentinel */ } }; @@ -623,6 +626,30 @@ check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope) return (need_wa > 0); } +static const __maybe_unused struct midr_range tx2_family_cpus[] = { + MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), + MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), + {}, +}; + +static bool __maybe_unused +needs_tx2_tvm_workaround(const struct arm64_cpu_capabilities *entry, + int scope) +{ + int i; + + if (!is_affected_midr_range_list(entry, scope) || + !is_hyp_mode_available()) + return false; + + for_each_possible_cpu(i) { + if (MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 0) != 0) + return true; + } + + return false; +} + #ifdef CONFIG_HARDEN_EL2_VECTORS static const struct midr_range arm64_harden_el2_vectors[] = { @@ -634,17 +661,23 @@ static const struct midr_range arm64_harden_el2_vectors[] = { #endif #ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI - -static const struct midr_range arm64_repeat_tlbi_cpus[] = { +static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = { #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009 - MIDR_RANGE(MIDR_QCOM_FALKOR_V1, 0, 0, 0, 0), + { + ERRATA_MIDR_REV(MIDR_QCOM_FALKOR_V1, 0, 0) + }, + { + .midr_range.model = MIDR_QCOM_KRYO, + .matches = is_kryo_midr, + }, #endif #ifdef CONFIG_ARM64_ERRATUM_1286807 - MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0), + { + ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0), + }, #endif {}, }; - #endif #ifdef CONFIG_CAVIUM_ERRATUM_27456 @@ -712,6 +745,33 @@ static const struct midr_range erratum_1418040_list[] = { }; #endif +#ifdef CONFIG_ARM64_ERRATUM_845719 +static const struct midr_range erratum_845719_list[] = { + /* Cortex-A53 r0p[01234] */ + MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4), + /* Brahma-B53 r0p[0] */ + MIDR_REV(MIDR_BRAHMA_B53, 0, 0), + {}, +}; +#endif + +#ifdef CONFIG_ARM64_ERRATUM_843419 +static const struct arm64_cpu_capabilities erratum_843419_list[] = { + { + /* Cortex-A53 r0p[01234] */ + .matches = is_affected_midr_range, + ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4), + MIDR_FIXED(0x4, BIT(8)), + }, + { + /* Brahma-B53 r0p[0] */ + .matches = is_affected_midr_range, + ERRATA_MIDR_REV(MIDR_BRAHMA_B53, 0, 0), + }, + {}, +}; +#endif + const struct arm64_cpu_capabilities arm64_errata[] = { #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE { @@ -743,19 +803,18 @@ const struct arm64_cpu_capabilities arm64_errata[] = { #endif #ifdef CONFIG_ARM64_ERRATUM_843419 { - /* Cortex-A53 r0p[01234] */ .desc = "ARM erratum 843419", .capability = ARM64_WORKAROUND_843419, - ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4), - MIDR_FIXED(0x4, BIT(8)), + .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, + .matches = cpucap_multi_entry_cap_matches, + .match_list = erratum_843419_list, }, #endif #ifdef CONFIG_ARM64_ERRATUM_845719 { - /* Cortex-A53 r0p[01234] */ .desc = "ARM erratum 845719", .capability = ARM64_WORKAROUND_845719, - ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4), + ERRATA_MIDR_RANGE_LIST(erratum_845719_list), }, #endif #ifdef CONFIG_CAVIUM_ERRATUM_23154 @@ -791,6 +850,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = { { .desc = "Qualcomm Technologies Falkor/Kryo erratum 1003", .capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003, + .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, .matches = cpucap_multi_entry_cap_matches, .match_list = qcom_erratum_1003_list, }, @@ -799,7 +859,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = { { .desc = "Qualcomm erratum 1009, ARM erratum 1286807", .capability = ARM64_WORKAROUND_REPEAT_TLBI, - ERRATA_MIDR_RANGE_LIST(arm64_repeat_tlbi_cpus), + .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, + .matches = cpucap_multi_entry_cap_matches, + .match_list = arm64_repeat_tlbi_list, }, #endif #ifdef CONFIG_ARM64_ERRATUM_858921 @@ -851,6 +913,19 @@ const struct arm64_cpu_capabilities arm64_errata[] = { .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, .matches = has_cortex_a76_erratum_1463225, }, +#endif +#ifdef CONFIG_CAVIUM_TX2_ERRATUM_219 + { + .desc = "Cavium ThunderX2 erratum 219 (KVM guest sysreg trapping)", + .capability = ARM64_WORKAROUND_CAVIUM_TX2_219_TVM, + ERRATA_MIDR_RANGE_LIST(tx2_family_cpus), + .matches = needs_tx2_tvm_workaround, + }, + { + .desc = "Cavium ThunderX2 erratum 219 (PRFM removal)", + .capability = ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM, + ERRATA_MIDR_RANGE_LIST(tx2_family_cpus), + }, #endif { } diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 02ba4f93504a9310a7717762a1e6adee07686c1c..1b845d264855e6b2450e9a698455229e92d32742 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -176,11 +176,16 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = { }; static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = { - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SM4_SHIFT, 4, 0), - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SHA3_SHIFT, 4, 0), - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_BITPERM_SHIFT, 4, 0), - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_AES_SHIFT, 4, 0), - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SVEVER_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), + FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SM4_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), + FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SHA3_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), + FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_BITPERM_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), + FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_AES_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), + FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SVEVER_SHIFT, 4, 0), ARM64_FTR_END, }; diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index e304fe04b098d813a2fd080ef17bba0cf67fdbd5..cf3bd2976e5747ff5c5b22ee0665700476133816 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -604,7 +604,7 @@ el1_da: */ mrs x3, far_el1 inherit_daif pstate=x23, tmp=x2 - clear_address_tag x0, x3 + untagged_addr x0, x3 mov x2, sp // struct pt_regs bl do_mem_abort @@ -680,7 +680,7 @@ alternative_if ARM64_HAS_IRQ_PRIO_MASKING orr x24, x24, x0 alternative_else_nop_endif cbnz x24, 1f // preempt count != 0 || NMI return path - bl preempt_schedule_irq // irq en/disable is done inside + bl arm64_preempt_schedule_irq // irq en/disable is done inside 1: #endif @@ -808,7 +808,7 @@ el0_da: mrs x26, far_el1 ct_user_exit_irqoff enable_daif - clear_address_tag x0, x26 + untagged_addr x0, x26 mov x1, x25 mov x2, sp bl do_mem_abort @@ -1071,7 +1071,9 @@ alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003 #else ldr x30, =vectors #endif +alternative_if_not ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM prfm plil1strm, [x30, #(1b - tramp_vectors)] +alternative_else_nop_endif msr vbar_el1, x30 add x30, x30, #(1b - tramp_vectors) isb diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index e0a7fce0e01c1d5533a6dd19fed7431dd3fa3ed5..a96b2921d22c2f12b4fdbb1bb1a4b918d8bd66c5 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -201,6 +201,7 @@ static int create_safe_exec_page(void *src_start, size_t length, gfp_t mask) { int rc = 0; + pgd_t *trans_pgd; pgd_t *pgdp; pud_t *pudp; pmd_t *pmdp; @@ -215,7 +216,13 @@ static int create_safe_exec_page(void *src_start, size_t length, memcpy((void *)dst, src_start, length); __flush_icache_range(dst, dst + length); - pgdp = pgd_offset_raw(allocator(mask), dst_addr); + trans_pgd = allocator(mask); + if (!trans_pgd) { + rc = -ENOMEM; + goto out; + } + + pgdp = pgd_offset_raw(trans_pgd, dst_addr); if (pgd_none(READ_ONCE(*pgdp))) { pudp = allocator(mask); if (!pudp) { diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 1fb2819fc048ebbed497c121ad24fba4c95f0712..71f788cd2b18772629c4627be979f75753253d08 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -631,3 +633,19 @@ static int __init tagged_addr_init(void) core_initcall(tagged_addr_init); #endif /* CONFIG_ARM64_TAGGED_ADDR_ABI */ + +asmlinkage void __sched arm64_preempt_schedule_irq(void) +{ + lockdep_assert_irqs_disabled(); + + /* + * Preempting a task from an IRQ means we leave copies of PSTATE + * on the stack. cpufeature's enable calls may modify PSTATE, but + * resuming one of these preempted tasks would undo those changes. + * + * Only allow a task to be preempted once cpufeatures have been + * enabled. + */ + if (static_branch_likely(&arm64_const_caps_ready)) + preempt_schedule_irq(); +} diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 3d3815020e3627488dbcf4de139ddf1709399178..799e84a403351df81d2f38d1e92f6e4850b7b002 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -124,6 +124,9 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) { u64 hcr = vcpu->arch.hcr_el2; + if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM)) + hcr |= HCR_TVM; + write_sysreg(hcr, hcr_el2); if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE)) @@ -174,8 +177,10 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu) * the crucial bit is "On taking a vSError interrupt, * HCR_EL2.VSE is cleared to 0." */ - if (vcpu->arch.hcr_el2 & HCR_VSE) - vcpu->arch.hcr_el2 = read_sysreg(hcr_el2); + if (vcpu->arch.hcr_el2 & HCR_VSE) { + vcpu->arch.hcr_el2 &= ~HCR_VSE; + vcpu->arch.hcr_el2 |= read_sysreg(hcr_el2) & HCR_VSE; + } if (has_vhe()) deactivate_traps_vhe(); @@ -380,6 +385,61 @@ static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu) return true; } +static bool __hyp_text handle_tx2_tvm(struct kvm_vcpu *vcpu) +{ + u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_hsr(vcpu)); + int rt = kvm_vcpu_sys_get_rt(vcpu); + u64 val = vcpu_get_reg(vcpu, rt); + + /* + * The normal sysreg handling code expects to see the traps, + * let's not do anything here. + */ + if (vcpu->arch.hcr_el2 & HCR_TVM) + return false; + + switch (sysreg) { + case SYS_SCTLR_EL1: + write_sysreg_el1(val, SYS_SCTLR); + break; + case SYS_TTBR0_EL1: + write_sysreg_el1(val, SYS_TTBR0); + break; + case SYS_TTBR1_EL1: + write_sysreg_el1(val, SYS_TTBR1); + break; + case SYS_TCR_EL1: + write_sysreg_el1(val, SYS_TCR); + break; + case SYS_ESR_EL1: + write_sysreg_el1(val, SYS_ESR); + break; + case SYS_FAR_EL1: + write_sysreg_el1(val, SYS_FAR); + break; + case SYS_AFSR0_EL1: + write_sysreg_el1(val, SYS_AFSR0); + break; + case SYS_AFSR1_EL1: + write_sysreg_el1(val, SYS_AFSR1); + break; + case SYS_MAIR_EL1: + write_sysreg_el1(val, SYS_MAIR); + break; + case SYS_AMAIR_EL1: + write_sysreg_el1(val, SYS_AMAIR); + break; + case SYS_CONTEXTIDR_EL1: + write_sysreg_el1(val, SYS_CONTEXTIDR); + break; + default: + return false; + } + + __kvm_skip_instr(vcpu); + return true; +} + /* * Return true when we were able to fixup the guest exit and should return to * the guest, false when we should restore the host state and return to the @@ -399,6 +459,11 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) if (*exit_code != ARM_EXCEPTION_TRAP) goto exit; + if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && + kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 && + handle_tx2_tvm(vcpu)) + return true; + /* * We trap the first access to the FP/SIMD to save the host context * and restore the guest context lazily. diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2071260a275bd236923da5650da86a012eaa5b4a..46822afc57e00461843b56f72cd403a939f17e69 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -632,6 +632,8 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) */ val = ((pmcr & ~ARMV8_PMU_PMCR_MASK) | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E); + if (!system_supports_32bit_el0()) + val |= ARMV8_PMU_PMCR_LC; __vcpu_sys_reg(vcpu, r->reg) = val; } @@ -682,6 +684,8 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, val = __vcpu_sys_reg(vcpu, PMCR_EL0); val &= ~ARMV8_PMU_PMCR_MASK; val |= p->regval & ARMV8_PMU_PMCR_MASK; + if (!system_supports_32bit_el0()) + val |= ARMV8_PMU_PMCR_LC; __vcpu_sys_reg(vcpu, PMCR_EL0) = val; kvm_pmu_handle_pmcr(vcpu, val); kvm_vcpu_pmu_restore_guest(vcpu); diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 855f2a7954e69e34037adf5cf4f38764254a7f5e..9fc6db0bcbad0636f2ee6919cc2a04d5f8bd4127 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -268,8 +268,12 @@ static bool __kprobes is_spurious_el1_translation_fault(unsigned long addr, par = read_sysreg(par_el1); local_irq_restore(flags); + /* + * If we now have a valid translation, treat the translation fault as + * spurious. + */ if (!(par & SYS_PAR_EL1_F)) - return false; + return true; /* * If we got a different type of fault from the AT instruction, diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index 77a836e661c9eea91bc7582dd6ed435f5aba8f90..df69eaa453a1c299b8467c3b972ef8a225fc5706 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -84,7 +84,7 @@ void __init prom_init(void) * Here we will start up CPU1 in the background and ask it to * reconfigure itself then go back to sleep. */ - memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20); + memcpy((void *)0xa0000200, bmips_smp_movevec, 0x20); __sync(); set_c0_cause(C_SW0); cpumask_set_cpu(1, &bmips_booted_mask); diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h index bf6a8afd7ad2783dff63cb55954a2e34d8ca6e79..581a6a3c66e405c6ea23cdfefc45690a2fe43209 100644 --- a/arch/mips/include/asm/bmips.h +++ b/arch/mips/include/asm/bmips.h @@ -75,11 +75,11 @@ static inline int register_bmips_smp_ops(void) #endif } -extern char bmips_reset_nmi_vec; -extern char bmips_reset_nmi_vec_end; -extern char bmips_smp_movevec; -extern char bmips_smp_int_vec; -extern char bmips_smp_int_vec_end; +extern char bmips_reset_nmi_vec[]; +extern char bmips_reset_nmi_vec_end[]; +extern char bmips_smp_movevec[]; +extern char bmips_smp_int_vec[]; +extern char bmips_smp_int_vec_end[]; extern int bmips_smp_enabled; extern int bmips_cpu_offset; diff --git a/arch/mips/include/asm/vdso/gettimeofday.h b/arch/mips/include/asm/vdso/gettimeofday.h index e78462e8ca2e74311028c78b6be52a186fc83b9a..b08825531e9f9a3ce89e926ffc3e096fbfe14fc0 100644 --- a/arch/mips/include/asm/vdso/gettimeofday.h +++ b/arch/mips/include/asm/vdso/gettimeofday.h @@ -24,6 +24,8 @@ #define VDSO_HAS_CLOCK_GETRES 1 +#define __VDSO_USE_SYSCALL ULLONG_MAX + #ifdef CONFIG_MIPS_CLOCK_VSYSCALL static __always_inline long gettimeofday_fallback( @@ -205,7 +207,7 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) break; #endif default: - cycle_now = 0; + cycle_now = __VDSO_USE_SYSCALL; break; } diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 76fae9b79f1312c1997e399f49d940494bd8b689..712c15de6ab9faa9d856b875963432d40ef610a1 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -464,10 +464,10 @@ static void bmips_wr_vec(unsigned long dst, char *start, char *end) static inline void bmips_nmi_handler_setup(void) { - bmips_wr_vec(BMIPS_NMI_RESET_VEC, &bmips_reset_nmi_vec, - &bmips_reset_nmi_vec_end); - bmips_wr_vec(BMIPS_WARM_RESTART_VEC, &bmips_smp_int_vec, - &bmips_smp_int_vec_end); + bmips_wr_vec(BMIPS_NMI_RESET_VEC, bmips_reset_nmi_vec, + bmips_reset_nmi_vec_end); + bmips_wr_vec(BMIPS_WARM_RESTART_VEC, bmips_smp_int_vec, + bmips_smp_int_vec_end); } struct reset_vec_info { diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index e01cb33bfa1a78a67638d5b27fb8fc7e43df3e09..41bb91f056885f5589e5b2a278cdcec2d83be659 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -653,6 +653,13 @@ static void build_restore_pagemask(u32 **p, struct uasm_reloc **r, int restore_scratch) { if (restore_scratch) { + /* + * Ensure the MFC0 below observes the value written to the + * KScratch register by the prior MTC0. + */ + if (scratch_reg >= 0) + uasm_i_ehb(p); + /* Reset default page size */ if (PM_DEFAULT_MASK >> 16) { uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16); @@ -667,12 +674,10 @@ static void build_restore_pagemask(u32 **p, struct uasm_reloc **r, uasm_i_mtc0(p, 0, C0_PAGEMASK); uasm_il_b(p, r, lid); } - if (scratch_reg >= 0) { - uasm_i_ehb(p); + if (scratch_reg >= 0) UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); - } else { + else UASM_i_LW(p, 1, scratchpad_offset(0), 0); - } } else { /* Reset default page size */ if (PM_DEFAULT_MASK >> 16) { @@ -921,6 +926,10 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, } if (mode != not_refill && check_for_high_segbits) { uasm_l_large_segbits_fault(l, *p); + + if (mode == refill_scratch && scratch_reg >= 0) + uasm_i_ehb(p); + /* * We get here if we are an xsseg address, or if we are * an xuseg address above (PGDIR_SHIFT+PGDIR_BITS) boundary. @@ -939,12 +948,10 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, uasm_i_jr(p, ptr); if (mode == refill_scratch) { - if (scratch_reg >= 0) { - uasm_i_ehb(p); + if (scratch_reg >= 0) UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); - } else { + else UASM_i_LW(p, 1, scratchpad_offset(0), 0); - } } else { uasm_i_nop(p); } diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index 73ca89a47f492702f5326525cd67d85be9f8076e..e5de3f89763397109028c242ef700e1f9683ed6d 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h @@ -22,7 +22,7 @@ #define ARCH_DMA_MINALIGN L1_CACHE_BYTES -#define __read_mostly __attribute__((__section__(".data..read_mostly"))) +#define __read_mostly __section(.data..read_mostly) void parisc_cache_init(void); /* initializes cache-flushing */ void disable_sr_hashing_asm(int); /* low level support for above */ diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h index 3eb4bfc1fb365478f11c9c87bfb3b3124fab567a..e080143e79a30576f4899e5b97a35f16a16b890b 100644 --- a/arch/parisc/include/asm/ldcw.h +++ b/arch/parisc/include/asm/ldcw.h @@ -52,7 +52,7 @@ }) #ifdef CONFIG_SMP -# define __lock_aligned __attribute__((__section__(".data..lock_aligned"))) +# define __lock_aligned __section(.data..lock_aligned) #endif #endif /* __PARISC_LDCW_H */ diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 1d1d748c227f075685f79dc327bfc52a029885d1..b96d7449697791260fdf2a28985ba7174f412668 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -2125,7 +2125,7 @@ ftrace_regs_caller: copy %rp, %r26 LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25 ldo -8(%r25), %r25 - copy %r3, %arg2 + ldo -FTRACE_FRAME_SIZE(%r1), %arg2 b,l ftrace_function_trampoline, %rp copy %r1, %arg3 /* struct pt_regs */ diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c index 92a9b5f12f98adfe4e87e6a18ff381e528108946..f29f682352f017fd2c55dd0ba34df9ac82a8c0c5 100644 --- a/arch/parisc/mm/ioremap.c +++ b/arch/parisc/mm/ioremap.c @@ -3,7 +3,7 @@ * arch/parisc/mm/ioremap.c * * (C) Copyright 1995 1996 Linus Torvalds - * (C) Copyright 2001-2006 Helge Deller + * (C) Copyright 2001-2019 Helge Deller * (C) Copyright 2005 Kyle McMartin */ @@ -84,7 +84,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l addr = (void __iomem *) area->addr; if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, phys_addr, pgprot)) { - vfree(addr); + vunmap(addr); return NULL; } @@ -92,9 +92,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l } EXPORT_SYMBOL(__ioremap); -void iounmap(const volatile void __iomem *addr) +void iounmap(const volatile void __iomem *io_addr) { - if (addr > high_memory) - return vfree((void *) (PAGE_MASK & (unsigned long __force) addr)); + unsigned long addr = (unsigned long)io_addr & PAGE_MASK; + + if (is_vmalloc_addr((void *)addr)) + vunmap((void *)addr); } EXPORT_SYMBOL(iounmap); diff --git a/arch/powerpc/include/asm/book3s/32/kup.h b/arch/powerpc/include/asm/book3s/32/kup.h index 677e9babef801305e61951244f0b32298c1725c7..f9dc597b0b86884dca4dc9c5e1814312bb34e41e 100644 --- a/arch/powerpc/include/asm/book3s/32/kup.h +++ b/arch/powerpc/include/asm/book3s/32/kup.h @@ -91,6 +91,7 @@ static inline void kuap_update_sr(u32 sr, u32 addr, u32 end) { + addr &= 0xf0000000; /* align addr to start of segment */ barrier(); /* make sure thread.kuap is updated before playing with SRs */ while (addr < end) { mtsrin(sr, addr); diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 409c9bfb43d9dff09e4413f1095e03eaf184f2b1..57c229a86f0811e783c9526283e617f96c485bbf 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -175,4 +175,7 @@ do { \ ARCH_DLINFO_CACHE_GEOMETRY; \ } while (0) +/* Relocate the kernel image to @final_address */ +void relocate(unsigned long final_address); + #endif /* _ASM_POWERPC_ELF_H */ diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index a4e7762dd28648ac5dc8e64bc96a6854b532087c..100f1b57ec2fd18531dd16b16c0885c0550f114c 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -3249,7 +3249,20 @@ static void setup_secure_guest(unsigned long kbase, unsigned long fdt) /* Switch to secure mode. */ prom_printf("Switching to secure mode.\n"); + /* + * The ultravisor will do an integrity check of the kernel image but we + * relocated it so the check will fail. Restore the original image by + * relocating it back to the kernel virtual base address. + */ + if (IS_ENABLED(CONFIG_RELOCATABLE)) + relocate(KERNELBASE); + ret = enter_secure_mode(kbase, fdt); + + /* Relocate the kernel again. */ + if (IS_ENABLED(CONFIG_RELOCATABLE)) + relocate(kbase); + if (ret != U_SUCCESS) { prom_printf("Returned %d from switching to secure mode.\n", ret); prom_rtas_os_term("Switch to secure mode failed.\n"); diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh index 78bab17b1396aefe35ac0a4573fbbbab39acd148..b183ab9c5107c9236930b3d3d9e1f2c7dd27b302 100644 --- a/arch/powerpc/kernel/prom_init_check.sh +++ b/arch/powerpc/kernel/prom_init_check.sh @@ -26,7 +26,8 @@ _end enter_prom $MEM_FUNCS reloc_offset __secondary_hold __secondary_hold_acknowledge __secondary_hold_spinloop __start logo_linux_clut224 btext_prepare_BAT reloc_got2 kernstart_addr memstart_addr linux_banner _stext -__prom_init_toc_start __prom_init_toc_end btext_setup_display TOC." +__prom_init_toc_start __prom_init_toc_end btext_setup_display TOC. +relocate" NM="$1" OBJ="$2" diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index 591bfb4bfd0fabb74cb2c81c35ff51acef8f58ba..a3f9c665bb5ba4c68039471c9e3b257cfd7814d3 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -1217,6 +1217,7 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev, struct kvmppc_xive *xive = dev->private; struct kvmppc_xive_vcpu *xc; int i, r = -EBUSY; + u32 vp_id; pr_devel("connect_vcpu(cpu=%d)\n", cpu); @@ -1228,25 +1229,32 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev, return -EPERM; if (vcpu->arch.irq_type != KVMPPC_IRQ_DEFAULT) return -EBUSY; - if (kvmppc_xive_find_server(vcpu->kvm, cpu)) { - pr_devel("Duplicate !\n"); - return -EEXIST; - } if (cpu >= (KVM_MAX_VCPUS * vcpu->kvm->arch.emul_smt_mode)) { pr_devel("Out of bounds !\n"); return -EINVAL; } - xc = kzalloc(sizeof(*xc), GFP_KERNEL); - if (!xc) - return -ENOMEM; /* We need to synchronize with queue provisioning */ mutex_lock(&xive->lock); + + vp_id = kvmppc_xive_vp(xive, cpu); + if (kvmppc_xive_vp_in_use(xive->kvm, vp_id)) { + pr_devel("Duplicate !\n"); + r = -EEXIST; + goto bail; + } + + xc = kzalloc(sizeof(*xc), GFP_KERNEL); + if (!xc) { + r = -ENOMEM; + goto bail; + } + vcpu->arch.xive_vcpu = xc; xc->xive = xive; xc->vcpu = vcpu; xc->server_num = cpu; - xc->vp_id = kvmppc_xive_vp(xive, cpu); + xc->vp_id = vp_id; xc->mfrr = 0xff; xc->valid = true; diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index 955b820ffd6da64f7c4471db47b271bbc1e8fafe..fe3ed50e081867676ce8af7a4930cfe1ccebd9fe 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h @@ -220,6 +220,18 @@ static inline u32 kvmppc_xive_vp(struct kvmppc_xive *xive, u32 server) return xive->vp_base + kvmppc_pack_vcpu_id(xive->kvm, server); } +static inline bool kvmppc_xive_vp_in_use(struct kvm *kvm, u32 vp_id) +{ + struct kvm_vcpu *vcpu = NULL; + int i; + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (vcpu->arch.xive_vcpu && vp_id == vcpu->arch.xive_vcpu->vp_id) + return true; + } + return false; +} + /* * Mapping between guest priorities and host priorities * is as follow. diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 248c1ea9e7881f2ebfc09f2149f5f7a4158ee413..78b906ffa0d2b8bc886fd2c004836d1bac122497 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -106,6 +106,7 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, struct kvmppc_xive *xive = dev->private; struct kvmppc_xive_vcpu *xc = NULL; int rc; + u32 vp_id; pr_devel("native_connect_vcpu(server=%d)\n", server_num); @@ -124,7 +125,8 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, mutex_lock(&xive->lock); - if (kvmppc_xive_find_server(vcpu->kvm, server_num)) { + vp_id = kvmppc_xive_vp(xive, server_num); + if (kvmppc_xive_vp_in_use(xive->kvm, vp_id)) { pr_devel("Duplicate !\n"); rc = -EEXIST; goto bail; @@ -141,7 +143,7 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev, xc->vcpu = vcpu; xc->server_num = server_num; - xc->vp_id = kvmppc_xive_vp(xive, server_num); + xc->vp_id = vp_id; xc->valid = true; vcpu->arch.irq_type = KVMPPC_IRQ_XIVE; diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 6bc24a47e9ef956e654ea022b4e6a9b52c0903df..6f300ab7f0e9b368114d65232d59d0a355d1201d 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -42,7 +42,7 @@ void pnv_pcibios_bus_add_device(struct pci_dev *pdev) { struct pci_dn *pdn = pci_get_pdn(pdev); - if (eeh_has_flag(EEH_FORCE_DISABLED)) + if (!pdn || eeh_has_flag(EEH_FORCE_DISABLED)) return; dev_dbg(&pdev->dev, "EEH: Setting up device\n"); diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index fbd6e6b7bbf28c4ac806681e4abd42e488504af8..13e25169934665e6655c780def5d3d056775d124 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c @@ -146,20 +146,25 @@ static int pnv_smp_cpu_disable(void) return 0; } +static void pnv_flush_interrupts(void) +{ + if (cpu_has_feature(CPU_FTR_ARCH_300)) { + if (xive_enabled()) + xive_flush_interrupt(); + else + icp_opal_flush_interrupt(); + } else { + icp_native_flush_interrupt(); + } +} + static void pnv_smp_cpu_kill_self(void) { + unsigned long srr1, unexpected_mask, wmask; unsigned int cpu; - unsigned long srr1, wmask; u64 lpcr_val; /* Standard hot unplug procedure */ - /* - * This hard disables local interurpts, ensuring we have no lazy - * irqs pending. - */ - WARN_ON(irqs_disabled()); - hard_irq_disable(); - WARN_ON(lazy_irq_pending()); idle_task_exit(); current->active_mm = NULL; /* for sanity */ @@ -172,6 +177,27 @@ static void pnv_smp_cpu_kill_self(void) if (cpu_has_feature(CPU_FTR_ARCH_207S)) wmask = SRR1_WAKEMASK_P8; + /* + * This turns the irq soft-disabled state we're called with, into a + * hard-disabled state with pending irq_happened interrupts cleared. + * + * PACA_IRQ_DEC - Decrementer should be ignored. + * PACA_IRQ_HMI - Can be ignored, processing is done in real mode. + * PACA_IRQ_DBELL, EE, PMI - Unexpected. + */ + hard_irq_disable(); + if (generic_check_cpu_restart(cpu)) + goto out; + + unexpected_mask = ~(PACA_IRQ_DEC | PACA_IRQ_HMI | PACA_IRQ_HARD_DIS); + if (local_paca->irq_happened & unexpected_mask) { + if (local_paca->irq_happened & PACA_IRQ_EE) + pnv_flush_interrupts(); + DBG("CPU%d Unexpected exit while offline irq_happened=%lx!\n", + cpu, local_paca->irq_happened); + } + local_paca->irq_happened = PACA_IRQ_HARD_DIS; + /* * We don't want to take decrementer interrupts while we are * offline, so clear LPCR:PECE1. We keep PECE2 (and @@ -197,6 +223,7 @@ static void pnv_smp_cpu_kill_self(void) srr1 = pnv_cpu_offline(cpu); + WARN_ON_ONCE(!irqs_disabled()); WARN_ON(lazy_irq_pending()); /* @@ -212,13 +239,7 @@ static void pnv_smp_cpu_kill_self(void) */ if (((srr1 & wmask) == SRR1_WAKEEE) || ((srr1 & wmask) == SRR1_WAKEHVI)) { - if (cpu_has_feature(CPU_FTR_ARCH_300)) { - if (xive_enabled()) - xive_flush_interrupt(); - else - icp_opal_flush_interrupt(); - } else - icp_native_flush_interrupt(); + pnv_flush_interrupts(); } else if ((srr1 & wmask) == SRR1_WAKEHDBELL) { unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); asm volatile(PPC_MSGCLR(%0) : : "r" (msg)); @@ -266,7 +287,7 @@ static void pnv_smp_cpu_kill_self(void) */ lpcr_val = mfspr(SPRN_LPCR) | (u64)LPCR_PECE1; pnv_program_cpu_hotplug_lpcr(cpu, lpcr_val); - +out: DBG("CPU%d coming online...\n", cpu); } diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts index 104d334511cd6b5d619496226bde06fb982f264a..88cfcb96bf233d3bb1c7677eb5526f6072e8ce77 100644 --- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts +++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts @@ -13,6 +13,7 @@ compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000"; chosen { + stdout-path = "serial0"; }; cpus { diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h index 07ceee8b17470a0e0aa9e6b4c03e378c0134d699..75604fec1b1b53fa954602b845f4d959494e595d 100644 --- a/arch/riscv/include/asm/bug.h +++ b/arch/riscv/include/asm/bug.h @@ -12,7 +12,6 @@ #include -#ifdef CONFIG_GENERIC_BUG #define __INSN_LENGTH_MASK _UL(0x3) #define __INSN_LENGTH_32 _UL(0x3) #define __COMPRESSED_INSN_MASK _UL(0xffff) @@ -20,7 +19,6 @@ #define __BUG_INSN_32 _UL(0x00100073) /* ebreak */ #define __BUG_INSN_16 _UL(0x9002) /* c.ebreak */ -#ifndef __ASSEMBLY__ typedef u32 bug_insn_t; #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS @@ -43,6 +41,7 @@ typedef u32 bug_insn_t; RISCV_SHORT " %2" #endif +#ifdef CONFIG_GENERIC_BUG #define __BUG_FLAGS(flags) \ do { \ __asm__ __volatile__ ( \ @@ -58,14 +57,10 @@ do { \ "i" (flags), \ "i" (sizeof(struct bug_entry))); \ } while (0) - -#endif /* !__ASSEMBLY__ */ #else /* CONFIG_GENERIC_BUG */ -#ifndef __ASSEMBLY__ #define __BUG_FLAGS(flags) do { \ __asm__ __volatile__ ("ebreak\n"); \ } while (0) -#endif /* !__ASSEMBLY__ */ #endif /* CONFIG_GENERIC_BUG */ #define BUG() do { \ @@ -79,15 +74,10 @@ do { \ #include -#ifndef __ASSEMBLY__ - struct pt_regs; struct task_struct; -extern void die(struct pt_regs *regs, const char *str); -extern void do_trap(struct pt_regs *regs, int signo, int code, - unsigned long addr); - -#endif /* !__ASSEMBLY__ */ +void die(struct pt_regs *regs, const char *str); +void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr); #endif /* _ASM_RISCV_BUG_H */ diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h index fc1189ad377728f7f307796731b43f3b5310f8ee..3ba4d93721d302ec79e94d96dc4bd1dac940c56e 100644 --- a/arch/riscv/include/asm/io.h +++ b/arch/riscv/include/asm/io.h @@ -13,6 +13,7 @@ #include #include +#include extern void __iomem *ioremap(phys_addr_t offset, unsigned long size); @@ -161,6 +162,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) #define writeq(v,c) ({ __io_bw(); writeq_cpu((v),(c)); __io_aw(); }) #endif +/* + * I/O port access constants. + */ +#define IO_SPACE_LIMIT (PCI_IO_SIZE - 1) +#define PCI_IOBASE ((void __iomem *)PCI_IO_START) + /* * Emulation routines for the port-mapped IO space used by some PCI drivers. * These are defined as being "fully synchronous", but also "not guaranteed to diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h index 75576424c0f70c20d34e95419224a08837ab363b..6e1b0e0325eb92a26bba60f7c08c7c32a37a45d0 100644 --- a/arch/riscv/include/asm/irq.h +++ b/arch/riscv/include/asm/irq.h @@ -7,6 +7,9 @@ #ifndef _ASM_RISCV_IRQ_H #define _ASM_RISCV_IRQ_H +#include +#include + #define NR_IRQS 0 void riscv_timer_interrupt(void); diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 7255f2d8395bb07fdd2ce5b4c002fa1581c7782d..d3221017194dd19bfe824683ecb700dee60d6e7b 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -7,6 +7,7 @@ #define _ASM_RISCV_PGTABLE_H #include +#include #include @@ -86,14 +87,7 @@ extern pgd_t swapper_pg_dir[]; #define VMALLOC_SIZE (KERN_VIRT_SIZE >> 1) #define VMALLOC_END (PAGE_OFFSET - 1) #define VMALLOC_START (PAGE_OFFSET - VMALLOC_SIZE) - -#define FIXADDR_TOP VMALLOC_START -#ifdef CONFIG_64BIT -#define FIXADDR_SIZE PMD_SIZE -#else -#define FIXADDR_SIZE PGDIR_SIZE -#endif -#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) +#define PCI_IO_SIZE SZ_16M /* * Roughly size the vmemmap space to be large enough to fit enough @@ -108,6 +102,17 @@ extern pgd_t swapper_pg_dir[]; #define vmemmap ((struct page *)VMEMMAP_START) +#define PCI_IO_END VMEMMAP_START +#define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) +#define FIXADDR_TOP PCI_IO_START + +#ifdef CONFIG_64BIT +#define FIXADDR_SIZE PMD_SIZE +#else +#define FIXADDR_SIZE PGDIR_SIZE +#endif +#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) + /* * ZERO_PAGE is a global shared page that is always zero, * used for zero-mapped memory areas, etc. @@ -184,10 +189,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot)); } -static inline pte_t mk_pte(struct page *page, pgprot_t prot) -{ - return pfn_pte(page_to_pfn(page), prot); -} +#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) @@ -428,9 +430,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -#ifdef CONFIG_FLATMEM #define kern_addr_valid(addr) (1) /* FIXME */ -#endif extern void *dtb_early_va; extern void setup_bootmem(void); diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h index f0227bdce0f0614925ae772dc80588b8828f2ec0..ee4f0ac62c9d7dce882489ae343965b3856c8cee 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -6,6 +6,7 @@ #ifndef _ASM_RISCV_SWITCH_TO_H #define _ASM_RISCV_SWITCH_TO_H +#include #include #include #include diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h index 37ae4e367ad203a55a56cfe47ee85202ed7f1781..f02188a5b0f41b4a193aa432014aaf68bf5cce28 100644 --- a/arch/riscv/include/asm/tlbflush.h +++ b/arch/riscv/include/asm/tlbflush.h @@ -10,10 +10,6 @@ #include #include -/* - * Flush entire local TLB. 'sfence.vma' implicitly fences with the instruction - * cache as well, so a 'fence.i' is not necessary. - */ static inline void local_flush_tlb_all(void) { __asm__ __volatile__ ("sfence.vma" : : : "memory"); diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index b1ade9a49347796cb550696f9c111af8ea9a9ead..a5ad00043104d3c16275f271649af64755c8de0e 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -10,6 +10,7 @@ #include #include #include +#include unsigned long elf_hwcap __read_mostly; #ifdef CONFIG_FPU diff --git a/arch/riscv/kernel/head.h b/arch/riscv/kernel/head.h new file mode 100644 index 0000000000000000000000000000000000000000..105fb0496b24d3bc0b15c6fc1ea88a6e806bc498 --- /dev/null +++ b/arch/riscv/kernel/head.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 SiFive, Inc. + */ +#ifndef __ASM_HEAD_H +#define __ASM_HEAD_H + +#include +#include + +extern atomic_t hart_lottery; + +asmlinkage void do_page_fault(struct pt_regs *regs); +asmlinkage void __init setup_vm(uintptr_t dtb_pa); + +extern void *__cpu_up_stack_pointer[]; +extern void *__cpu_up_task_pointer[]; + +void __init parse_dtb(void); + +#endif /* __ASM_HEAD_H */ diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c index 6d8659388c4922e1bb4bf5f67121e3407f570129..fffac6ddb0e00412fa76546cfdc0166eb5d4ed30 100644 --- a/arch/riscv/kernel/irq.c +++ b/arch/riscv/kernel/irq.c @@ -24,7 +24,7 @@ int arch_show_interrupts(struct seq_file *p, int prec) return 0; } -asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs) +asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); diff --git a/arch/riscv/kernel/module-sections.c b/arch/riscv/kernel/module-sections.c index c9ae48333114ededcd0604e1a6bbf3291995e289..e264e59e596e80d71166107f7b5763f74fbf02c8 100644 --- a/arch/riscv/kernel/module-sections.c +++ b/arch/riscv/kernel/module-sections.c @@ -8,6 +8,7 @@ #include #include #include +#include unsigned long module_emit_got_entry(struct module *mod, unsigned long val) { diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index fb3a082362eb87554ff297f3e026d9663c5a8044..85e3c39bb60bcfa4634212cb3c8a52d06953cf89 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -7,6 +7,7 @@ * Copyright (C) 2017 SiFive */ +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include extern asmlinkage void ret_from_fork(void); extern asmlinkage void ret_from_kernel_thread(void); diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index 3687514383669028d9717c35b956b21af5bb1c0e..1252113ef8b2ca9bedd507acdaf7343e5ced13eb 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -148,7 +148,7 @@ long arch_ptrace(struct task_struct *child, long request, * Allows PTRACE_SYSCALL to work. These are called from entry.S in * {handle,ret_from}_syscall. */ -void do_syscall_trace_enter(struct pt_regs *regs) +__visible void do_syscall_trace_enter(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) if (tracehook_report_syscall_entry(regs)) @@ -162,7 +162,7 @@ void do_syscall_trace_enter(struct pt_regs *regs) audit_syscall_entry(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3); } -void do_syscall_trace_exit(struct pt_regs *regs) +__visible void do_syscall_trace_exit(struct pt_regs *regs) { audit_syscall_exit(regs); diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c index d0fe623bfb8f31c9a56e9f90ce25ec2b192a2a89..aa56bb135ec49f25dbe989e8b425b1a67c80a740 100644 --- a/arch/riscv/kernel/reset.c +++ b/arch/riscv/kernel/reset.c @@ -4,6 +4,7 @@ */ #include +#include #include static void default_power_off(void) diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index a990a6cb184f2e2c66a1abeafe3958020a9b2f2a..845ae0e121159719115cc818e096aa0bc621970b 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -24,6 +24,8 @@ #include #include +#include "head.h" + #ifdef CONFIG_DUMMY_CONSOLE struct screen_info screen_info = { .orig_video_lines = 30, diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index b14d7647d80014fd1982487b726b563def29775a..d0f6f212f5dfde4e8ef044af3b7c2bca316fabcf 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -26,7 +26,7 @@ struct rt_sigframe { #ifdef CONFIG_FPU static long restore_fp_state(struct pt_regs *regs, - union __riscv_fp_state *sc_fpregs) + union __riscv_fp_state __user *sc_fpregs) { long err; struct __riscv_d_ext_state __user *state = &sc_fpregs->d; @@ -53,7 +53,7 @@ static long restore_fp_state(struct pt_regs *regs, } static long save_fp_state(struct pt_regs *regs, - union __riscv_fp_state *sc_fpregs) + union __riscv_fp_state __user *sc_fpregs) { long err; struct __riscv_d_ext_state __user *state = &sc_fpregs->d; @@ -292,8 +292,8 @@ static void do_signal(struct pt_regs *regs) * notification of userspace execution resumption * - triggered by the _TIF_WORK_MASK flags */ -asmlinkage void do_notify_resume(struct pt_regs *regs, - unsigned long thread_info_flags) +asmlinkage __visible void do_notify_resume(struct pt_regs *regs, + unsigned long thread_info_flags) { /* Handle pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index b18cd6c8e8fbbf8383b0149da14be73b3c89f328..5c9ec78422c229490556295c7bbdb65def2a2fae 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -8,7 +8,9 @@ * Copyright (C) 2017 SiFive */ +#include #include +#include #include #include #include diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index 18ae6da5115e53d4612f84dc8a0898b863e8b55e..261f4087cc39e177fbc063b003dfafc57488cc18 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -29,6 +29,9 @@ #include #include #include +#include + +#include "head.h" void *__cpu_up_stack_pointer[NR_CPUS]; void *__cpu_up_task_pointer[NR_CPUS]; @@ -130,7 +133,7 @@ void __init smp_cpus_done(unsigned int max_cpus) /* * C entry point for a secondary processor. */ -asmlinkage void __init smp_callin(void) +asmlinkage __visible void __init smp_callin(void) { struct mm_struct *mm = &init_mm; diff --git a/arch/riscv/kernel/syscall_table.c b/arch/riscv/kernel/syscall_table.c index e5dd52d8f6332b4566787243b7a90313939f97d0..f1ead9df96ca55b11fc7319cfc7b852a7d019676 100644 --- a/arch/riscv/kernel/syscall_table.c +++ b/arch/riscv/kernel/syscall_table.c @@ -8,6 +8,7 @@ #include #include #include +#include #undef __SYSCALL #define __SYSCALL(nr, call) [nr] = (call), diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c index 9dd1f2e64db12089aac4cdd8d65ec9d543950a08..6a53c02e9c734c6db04e6236580ace56f0d27b19 100644 --- a/arch/riscv/kernel/time.c +++ b/arch/riscv/kernel/time.c @@ -7,6 +7,7 @@ #include #include #include +#include unsigned long riscv_timebase; EXPORT_SYMBOL_GPL(riscv_timebase); diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 93742df9067fb5c864139445c414273bb9cd7168..473de3ae8bb75766ded32ec9ae35b1d4549e156b 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -3,6 +3,7 @@ * Copyright (C) 2012 Regents of the University of California */ +#include #include #include #include @@ -83,7 +84,7 @@ static void do_trap_error(struct pt_regs *regs, int signo, int code, } #define DO_ERROR_INFO(name, signo, code, str) \ -asmlinkage void name(struct pt_regs *regs) \ +asmlinkage __visible void name(struct pt_regs *regs) \ { \ do_trap_error(regs, signo, code, regs->sepc, "Oops - " str); \ } @@ -111,7 +112,6 @@ DO_ERROR_INFO(do_trap_ecall_s, DO_ERROR_INFO(do_trap_ecall_m, SIGILL, ILL_ILLTRP, "environment call from M-mode"); -#ifdef CONFIG_GENERIC_BUG static inline unsigned long get_break_insn_length(unsigned long pc) { bug_insn_t insn; @@ -120,28 +120,15 @@ static inline unsigned long get_break_insn_length(unsigned long pc) return 0; return (((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) ? 4UL : 2UL); } -#endif /* CONFIG_GENERIC_BUG */ -asmlinkage void do_trap_break(struct pt_regs *regs) +asmlinkage __visible void do_trap_break(struct pt_regs *regs) { - if (!user_mode(regs)) { - enum bug_trap_type type; - - type = report_bug(regs->sepc, regs); - switch (type) { -#ifdef CONFIG_GENERIC_BUG - case BUG_TRAP_TYPE_WARN: - regs->sepc += get_break_insn_length(regs->sepc); - return; - case BUG_TRAP_TYPE_BUG: -#endif /* CONFIG_GENERIC_BUG */ - default: - die(regs, "Kernel BUG"); - } - } else { - force_sig_fault(SIGTRAP, TRAP_BRKPT, - (void __user *)(regs->sepc)); - } + if (user_mode(regs)) + force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->sepc); + else if (report_bug(regs->sepc, regs) == BUG_TRAP_TYPE_WARN) + regs->sepc += get_break_insn_length(regs->sepc); + else + die(regs, "Kernel BUG"); } #ifdef CONFIG_GENERIC_BUG diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c index c9c21e0d56417cf3ebb3ccab116f44710da1b31f..484d95a70907afba706aec216ffc16450fb39e9d 100644 --- a/arch/riscv/kernel/vdso.c +++ b/arch/riscv/kernel/vdso.c @@ -6,6 +6,7 @@ * Copyright (C) 2015 Regents of the University of California */ +#include #include #include #include @@ -25,7 +26,7 @@ static union { struct vdso_data data; u8 page[PAGE_SIZE]; } vdso_data_store __page_aligned_data; -struct vdso_data *vdso_data = &vdso_data_store.data; +static struct vdso_data *vdso_data = &vdso_data_store.data; static int __init vdso_init(void) { diff --git a/arch/riscv/mm/context.c b/arch/riscv/mm/context.c index beeb5d7f92ea5aaccefc10e41ea036f5554da81a..ca66d44156b628d087fe1b2fc75c35f27f14e38f 100644 --- a/arch/riscv/mm/context.c +++ b/arch/riscv/mm/context.c @@ -7,6 +7,7 @@ #include #include #include +#include /* * When necessary, performs a deferred icache flush for the given MM context, diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 96add1427a75a5790acd3add530f33422c0808d9..247b8c859c448ae16467b3c8e8b620adfaa94dfd 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -18,6 +18,8 @@ #include #include +#include "../kernel/head.h" + /* * This routine handles page faults. It determines the address and the * problem, and then passes it off to one of the appropriate routines. diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 83f7d12042fbc781ab91a3a90c70043400f66c81..573463d1c799a0425e550681507643a9e60fe1cb 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -19,6 +19,8 @@ #include #include +#include "../kernel/head.h" + unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss; EXPORT_SYMBOL(empty_zero_page); @@ -337,8 +339,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) */ #ifndef __riscv_cmodel_medany -#error "setup_vm() is called from head.S before relocate so it should " - "not use absolute addressing." +#error "setup_vm() is called from head.S before relocate so it should not use absolute addressing." #endif asmlinkage void __init setup_vm(uintptr_t dtb_pa) @@ -458,7 +459,7 @@ void __init paging_init(void) zone_sizes_init(); } -#ifdef CONFIG_SPARSEMEM +#ifdef CONFIG_SPARSEMEM_VMEMMAP int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap) { diff --git a/arch/riscv/mm/sifive_l2_cache.c b/arch/riscv/mm/sifive_l2_cache.c index 2e637ad71c05f099b5e4e45f1abb39bac5991d64..a9ffff3277c77fa7b1847e45b890689aed909d7c 100644 --- a/arch/riscv/mm/sifive_l2_cache.c +++ b/arch/riscv/mm/sifive_l2_cache.c @@ -142,7 +142,7 @@ static irqreturn_t l2_int_handler(int irq, void *device) return IRQ_HANDLED; } -int __init sifive_l2_init(void) +static int __init sifive_l2_init(void) { struct device_node *np; struct resource res; diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 596ca7cc4d7b88a7c37b93cc58d87651ffe4bd9d..5367950510f695ae4c970dfa511f78456259a933 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -101,10 +101,18 @@ static void handle_relocs(unsigned long offset) dynsym = (Elf64_Sym *) vmlinux.dynsym_start; for (rela = rela_start; rela < rela_end; rela++) { loc = rela->r_offset + offset; - val = rela->r_addend + offset; + val = rela->r_addend; r_sym = ELF64_R_SYM(rela->r_info); - if (r_sym) - val += dynsym[r_sym].st_value; + if (r_sym) { + if (dynsym[r_sym].st_shndx != SHN_UNDEF) + val += dynsym[r_sym].st_value + offset; + } else { + /* + * 0 == undefined symbol table index (STN_UNDEF), + * used for R_390_RELATIVE, only add KASLR offset + */ + val += offset; + } r_type = ELF64_R_TYPE(rela->r_info); rc = arch_kexec_do_relocs(r_type, (void *) loc, val, 0); if (rc) diff --git a/arch/s390/include/asm/unwind.h b/arch/s390/include/asm/unwind.h index d827b5b9a32cd6a44d7beddba18b96cdcbb18aa9..eaaefeceef6f0810c53108b390420b351257a052 100644 --- a/arch/s390/include/asm/unwind.h +++ b/arch/s390/include/asm/unwind.h @@ -35,6 +35,7 @@ struct unwind_state { struct task_struct *task; struct pt_regs *regs; unsigned long sp, ip; + bool reuse_sp; int graph_idx; bool reliable; bool error; diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c index b9d8fe45737aa2e529cb9eec244349e121803858..8f8456816d83e890a3f3150ccec184f21810a509 100644 --- a/arch/s390/kernel/idle.c +++ b/arch/s390/kernel/idle.c @@ -69,18 +69,26 @@ DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); static ssize_t show_idle_time(struct device *dev, struct device_attribute *attr, char *buf) { + unsigned long long now, idle_time, idle_enter, idle_exit, in_idle; struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); - unsigned long long now, idle_time, idle_enter, idle_exit; unsigned int seq; do { - now = get_tod_clock(); seq = read_seqcount_begin(&idle->seqcount); idle_time = READ_ONCE(idle->idle_time); idle_enter = READ_ONCE(idle->clock_idle_enter); idle_exit = READ_ONCE(idle->clock_idle_exit); } while (read_seqcount_retry(&idle->seqcount, seq)); - idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; + in_idle = 0; + now = get_tod_clock(); + if (idle_enter) { + if (idle_exit) { + in_idle = idle_exit - idle_enter; + } else if (now > idle_enter) { + in_idle = now - idle_enter; + } + } + idle_time += in_idle; return sprintf(buf, "%llu\n", idle_time >> 12); } DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); @@ -88,17 +96,24 @@ DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL); u64 arch_cpu_idle_time(int cpu) { struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); - unsigned long long now, idle_enter, idle_exit; + unsigned long long now, idle_enter, idle_exit, in_idle; unsigned int seq; do { - now = get_tod_clock(); seq = read_seqcount_begin(&idle->seqcount); idle_enter = READ_ONCE(idle->clock_idle_enter); idle_exit = READ_ONCE(idle->clock_idle_exit); } while (read_seqcount_retry(&idle->seqcount, seq)); - - return cputime_to_nsecs(idle_enter ? ((idle_exit ?: now) - idle_enter) : 0); + in_idle = 0; + now = get_tod_clock(); + if (idle_enter) { + if (idle_exit) { + in_idle = idle_exit - idle_enter; + } else if (now > idle_enter) { + in_idle = now - idle_enter; + } + } + return cputime_to_nsecs(in_idle); } void arch_cpu_idle_enter(void) diff --git a/arch/s390/kernel/machine_kexec_reloc.c b/arch/s390/kernel/machine_kexec_reloc.c index 3b664cb3ec4d3b57ba3ca53fa2c3af1d8f92f9e1..d5035de9020e738819a06b9e0ecf74b77879ac4d 100644 --- a/arch/s390/kernel/machine_kexec_reloc.c +++ b/arch/s390/kernel/machine_kexec_reloc.c @@ -27,6 +27,7 @@ int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val, *(u32 *)loc = val; break; case R_390_64: /* Direct 64 bit. */ + case R_390_GLOB_DAT: *(u64 *)loc = val; break; case R_390_PC16: /* PC relative 16 bit. */ diff --git a/arch/s390/kernel/unwind_bc.c b/arch/s390/kernel/unwind_bc.c index 8fc9daae47a2ee89a25161ff9775673ee9f37dd8..a8204f952315d9edda9090a1d3762e37cc5fb99c 100644 --- a/arch/s390/kernel/unwind_bc.c +++ b/arch/s390/kernel/unwind_bc.c @@ -46,10 +46,15 @@ bool unwind_next_frame(struct unwind_state *state) regs = state->regs; if (unlikely(regs)) { - sp = READ_ONCE_NOCHECK(regs->gprs[15]); - if (unlikely(outside_of_stack(state, sp))) { - if (!update_stack_info(state, sp)) - goto out_err; + if (state->reuse_sp) { + sp = state->sp; + state->reuse_sp = false; + } else { + sp = READ_ONCE_NOCHECK(regs->gprs[15]); + if (unlikely(outside_of_stack(state, sp))) { + if (!update_stack_info(state, sp)) + goto out_err; + } } sf = (struct stack_frame *) sp; ip = READ_ONCE_NOCHECK(sf->gprs[8]); @@ -107,9 +112,9 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, { struct stack_info *info = &state->stack_info; unsigned long *mask = &state->stack_mask; + bool reliable, reuse_sp; struct stack_frame *sf; unsigned long ip; - bool reliable; memset(state, 0, sizeof(*state)); state->task = task; @@ -134,10 +139,12 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, if (regs) { ip = READ_ONCE_NOCHECK(regs->psw.addr); reliable = true; + reuse_sp = true; } else { sf = (struct stack_frame *) sp; ip = READ_ONCE_NOCHECK(sf->gprs[8]); reliable = false; + reuse_sp = false; } #ifdef CONFIG_FUNCTION_GRAPH_TRACER @@ -151,5 +158,6 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task, state->sp = sp; state->ip = ip; state->reliable = reliable; + state->reuse_sp = reuse_sp; } EXPORT_SYMBOL_GPL(__unwind_start); diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 510a18299196f3b797be51fd22b2bbfbe5cd003f..a51c892f14f3ee5bd393ed74003c96fd80268979 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -298,16 +298,16 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write, } if (write) { - len = *lenp; - if (copy_from_user(buf, buffer, - len > sizeof(buf) ? sizeof(buf) : len)) + len = min(*lenp, sizeof(buf)); + if (copy_from_user(buf, buffer, len)) return -EFAULT; - buf[sizeof(buf) - 1] = '\0'; + buf[len - 1] = '\0'; cmm_skip_blanks(buf, &p); nr = simple_strtoul(p, &p, 0); cmm_skip_blanks(p, &p); seconds = simple_strtoul(p, &p, 0); cmm_set_timeout(nr, seconds); + *ppos += *lenp; } else { len = sprintf(buf, "%ld %ld\n", cmm_timeout_pages, cmm_timeout_seconds); @@ -315,9 +315,9 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write, len = *lenp; if (copy_to_user(buffer, buf, len)) return -EFAULT; + *lenp = len; + *ppos += len; } - *lenp = len; - *ppos += len; return 0; } diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index fbc1aecf0f94ce085bc099c82c2b4a555e7a8b6c..eb24cb1afc11fbcc044583c3277b55aca9234f71 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -29,7 +29,6 @@ config SPARC select RTC_DRV_M48T59 select RTC_SYSTOHC select HAVE_ARCH_JUMP_LABEL if SPARC64 - select HAVE_FAST_GUP if SPARC64 select GENERIC_IRQ_SHOW select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_PCI_IOMAP diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 612535cd97065beecb42bb59c4d2d4ca8252f6c4..6627d7c30f3700954ca655527b3490dbf28dacde 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1403,8 +1403,12 @@ static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx, spin_unlock_irq(&ubd_dev->lock); - if (ret < 0) - blk_mq_requeue_request(req, true); + if (ret < 0) { + if (ret == -ENOMEM) + res = BLK_STS_RESOURCE; + else + res = BLK_STS_DEV_RESOURCE; + } return res; } diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 408bb5532d1ba151f569eb70b0b8be04072cfad7..94df0868804bcb4b9b37f7abf4985ac95158c4f8 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -298,6 +298,10 @@ vdso_install: archprepare: checkbin checkbin: +ifndef CONFIG_CC_HAS_ASM_GOTO + @echo Compiler lacks asm-goto support. + @exit 1 +endif ifdef CONFIG_RETPOLINE ifeq ($(RETPOLINE_CFLAGS),) @echo "You are building kernel with non-retpoline compiler." >&2 diff --git a/arch/x86/boot/compressed/acpi.c b/arch/x86/boot/compressed/acpi.c index 149795c369f275d241ffaa7c28106bd184c99b1c..25019d42ae937eeae4798115ea9995eaaa744dda 100644 --- a/arch/x86/boot/compressed/acpi.c +++ b/arch/x86/boot/compressed/acpi.c @@ -20,30 +20,6 @@ */ struct mem_vector immovable_mem[MAX_NUMNODES*2]; -/* - * Max length of 64-bit hex address string is 19, prefix "0x" + 16 hex - * digits, and '\0' for termination. - */ -#define MAX_ADDR_LEN 19 - -static acpi_physical_address get_cmdline_acpi_rsdp(void) -{ - acpi_physical_address addr = 0; - -#ifdef CONFIG_KEXEC - char val[MAX_ADDR_LEN] = { }; - int ret; - - ret = cmdline_find_option("acpi_rsdp", val, MAX_ADDR_LEN); - if (ret < 0) - return 0; - - if (kstrtoull(val, 16, &addr)) - return 0; -#endif - return addr; -} - /* * Search EFI system tables for RSDP. If both ACPI_20_TABLE_GUID and * ACPI_TABLE_GUID are found, take the former, which has more features. @@ -298,6 +274,30 @@ acpi_physical_address get_rsdp_addr(void) } #if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_MEMORY_HOTREMOVE) +/* + * Max length of 64-bit hex address string is 19, prefix "0x" + 16 hex + * digits, and '\0' for termination. + */ +#define MAX_ADDR_LEN 19 + +static acpi_physical_address get_cmdline_acpi_rsdp(void) +{ + acpi_physical_address addr = 0; + +#ifdef CONFIG_KEXEC + char val[MAX_ADDR_LEN] = { }; + int ret; + + ret = cmdline_find_option("acpi_rsdp", val, MAX_ADDR_LEN); + if (ret < 0) + return 0; + + if (kstrtoull(val, 16, &addr)) + return 0; +#endif + return addr; +} + /* Compute SRAT address from RSDP. */ static unsigned long get_acpi_srat_table(void) { diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index d6662fdef3001da7465dda8df8aed58a48fe6f58..82bc60c8acb240c29f925df7dde03ac724edf3b4 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "../string.h" #include "eboot.h" @@ -813,7 +814,8 @@ efi_main(struct efi_config *c, struct boot_params *boot_params) status = efi_relocate_kernel(sys_table, &bzimage_addr, hdr->init_size, hdr->init_size, hdr->pref_address, - hdr->kernel_alignment); + hdr->kernel_alignment, + LOAD_PHYSICAL_ADDR); if (status != EFI_SUCCESS) { efi_printk(sys_table, "efi_relocate_kernel() failed!\n"); goto fail; diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 53ac0cb2396da1b336bdb6b4375fe8bd977bbb32..9652d5c2afda84d5bf2dbfa6ad67f53f855609ff 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -345,6 +345,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, { const unsigned long kernel_total_size = VO__end - VO__text; unsigned long virt_addr = LOAD_PHYSICAL_ADDR; + unsigned long needed_size; /* Retain x86 boot parameters pointer passed from startup_32/64. */ boot_params = rmode; @@ -379,26 +380,38 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap, free_mem_ptr = heap; /* Heap */ free_mem_end_ptr = heap + BOOT_HEAP_SIZE; + /* + * The memory hole needed for the kernel is the larger of either + * the entire decompressed kernel plus relocation table, or the + * entire decompressed kernel plus .bss and .brk sections. + * + * On X86_64, the memory is mapped with PMD pages. Round the + * size up so that the full extent of PMD pages mapped is + * included in the check against the valid memory table + * entries. This ensures the full mapped area is usable RAM + * and doesn't include any reserved areas. + */ + needed_size = max(output_len, kernel_total_size); +#ifdef CONFIG_X86_64 + needed_size = ALIGN(needed_size, MIN_KERNEL_ALIGN); +#endif + /* Report initial kernel position details. */ debug_putaddr(input_data); debug_putaddr(input_len); debug_putaddr(output); debug_putaddr(output_len); debug_putaddr(kernel_total_size); + debug_putaddr(needed_size); #ifdef CONFIG_X86_64 /* Report address of 32-bit trampoline */ debug_putaddr(trampoline_32bit); #endif - /* - * The memory hole needed for the kernel is the larger of either - * the entire decompressed kernel plus relocation table, or the - * entire decompressed kernel plus .bss and .brk sections. - */ choose_random_location((unsigned long)input_data, input_len, (unsigned long *)&output, - max(output_len, kernel_total_size), + needed_size, &virt_addr); /* Validate memory location choices. */ diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig index 949c449b9d1f7436cb00f44d01dea63ee53b4f15..dc8c330bd77529d014af03f2569e827af198fcd4 100644 --- a/arch/x86/configs/gki_defconfig +++ b/arch/x86/configs/gki_defconfig @@ -14,6 +14,7 @@ CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_SCHED_AUTOGROUP=y @@ -46,11 +47,14 @@ CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set CONFIG_CPU_FREQ_TIMES=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPUFREQ_DUMMY=m CONFIG_IA32_EMULATION=y CONFIG_KPROBES=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_GKI_HACKS_TO_FIX=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_TRANSPARENT_HUGEPAGE=y @@ -233,7 +237,7 @@ CONFIG_USB_USBNET=y # CONFIG_WLAN_VENDOR_QUANTENNA is not set CONFIG_VIRT_WIFI=m CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_KEYBOARD is not set +CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y CONFIG_INPUT_MISC=y @@ -256,7 +260,6 @@ CONFIG_GPIOLIB=y CONFIG_DEVFREQ_THERMAL=y # CONFIG_X86_PKG_TEMP_THERMAL is not set CONFIG_REGULATOR=y -CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_DRM=y # CONFIG_DRM_FBDEV_EMULATION is not set @@ -315,6 +318,7 @@ CONFIG_EXT4_FS_SECURITY=y CONFIG_F2FS_FS=y CONFIG_F2FS_FS_SECURITY=y CONFIG_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_FS_VERITY=y CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y # CONFIG_DNOTIFY is not set @@ -384,6 +388,7 @@ CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_HARDENED_USERCOPY=y +CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_CRYPTO_ADIANTUM=y CONFIG_CRYPTO_SHA256_SSSE3=y diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c index 5b35b7ea5d7282d870b7d0d2a519620793deba76..26c36357c4c9c6b809abb04d07e43aba80675bf3 100644 --- a/arch/x86/events/amd/ibs.c +++ b/arch/x86/events/amd/ibs.c @@ -377,7 +377,8 @@ static inline void perf_ibs_disable_event(struct perf_ibs *perf_ibs, struct hw_perf_event *hwc, u64 config) { config &= ~perf_ibs->cnt_mask; - wrmsrl(hwc->config_base, config); + if (boot_cpu_data.x86 == 0x10) + wrmsrl(hwc->config_base, config); config &= ~perf_ibs->enable_mask; wrmsrl(hwc->config_base, config); } @@ -553,7 +554,8 @@ static struct perf_ibs perf_ibs_op = { }, .msr = MSR_AMD64_IBSOPCTL, .config_mask = IBS_OP_CONFIG_MASK, - .cnt_mask = IBS_OP_MAX_CNT, + .cnt_mask = IBS_OP_MAX_CNT | IBS_OP_CUR_CNT | + IBS_OP_CUR_CNT_RAND, .enable_mask = IBS_OP_ENABLE, .valid_mask = IBS_OP_VAL, .max_period = IBS_OP_MAX_CNT << 4, @@ -614,7 +616,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) if (event->attr.sample_type & PERF_SAMPLE_RAW) offset_max = perf_ibs->offset_max; else if (check_rip) - offset_max = 2; + offset_max = 3; else offset_max = 1; do { diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index 74e80ed9c6c474551b57c6d8b4d548aeb3ea8e4d..05e43d0f430bcdfd89999dc3e31369b49ad0ca4c 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -627,7 +627,7 @@ static struct topa *topa_alloc(int cpu, gfp_t gfp) * link as the 2nd entry in the table */ if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) { - TOPA_ENTRY(&tp->topa, 1)->base = page_to_phys(p); + TOPA_ENTRY(&tp->topa, 1)->base = page_to_phys(p) >> TOPA_SHIFT; TOPA_ENTRY(&tp->topa, 1)->end = 1; } diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index 6fc2e06ab4c6f9dfa45feb6f8762c97546203b2d..86467f85c383100789d0430a80ffc4989d12af03 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -502,10 +502,8 @@ void uncore_pmu_event_start(struct perf_event *event, int flags) local64_set(&event->hw.prev_count, uncore_read_counter(box, event)); uncore_enable_event(box, event); - if (box->n_active == 1) { - uncore_enable_box(box); + if (box->n_active == 1) uncore_pmu_start_hrtimer(box); - } } void uncore_pmu_event_stop(struct perf_event *event, int flags) @@ -529,10 +527,8 @@ void uncore_pmu_event_stop(struct perf_event *event, int flags) WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); hwc->state |= PERF_HES_STOPPED; - if (box->n_active == 0) { - uncore_disable_box(box); + if (box->n_active == 0) uncore_pmu_cancel_hrtimer(box); - } } if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { @@ -778,6 +774,40 @@ static int uncore_pmu_event_init(struct perf_event *event) return ret; } +static void uncore_pmu_enable(struct pmu *pmu) +{ + struct intel_uncore_pmu *uncore_pmu; + struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); + if (!uncore_pmu) + return; + + box = uncore_pmu_to_box(uncore_pmu, smp_processor_id()); + if (!box) + return; + + if (uncore_pmu->type->ops->enable_box) + uncore_pmu->type->ops->enable_box(box); +} + +static void uncore_pmu_disable(struct pmu *pmu) +{ + struct intel_uncore_pmu *uncore_pmu; + struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); + if (!uncore_pmu) + return; + + box = uncore_pmu_to_box(uncore_pmu, smp_processor_id()); + if (!box) + return; + + if (uncore_pmu->type->ops->disable_box) + uncore_pmu->type->ops->disable_box(box); +} + static ssize_t uncore_get_attr_cpumask(struct device *dev, struct device_attribute *attr, char *buf) { @@ -803,6 +833,8 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu) pmu->pmu = (struct pmu) { .attr_groups = pmu->type->attr_groups, .task_ctx_nr = perf_invalid_context, + .pmu_enable = uncore_pmu_enable, + .pmu_disable = uncore_pmu_disable, .event_init = uncore_pmu_event_init, .add = uncore_pmu_event_add, .del = uncore_pmu_event_del, diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h index f36f7bebbc1bbaca769c9f978efda52fa9e39897..bbfdaa720b4568ded56b575d366febf6e296e319 100644 --- a/arch/x86/events/intel/uncore.h +++ b/arch/x86/events/intel/uncore.h @@ -441,18 +441,6 @@ static inline int uncore_freerunning_hw_config(struct intel_uncore_box *box, return -EINVAL; } -static inline void uncore_disable_box(struct intel_uncore_box *box) -{ - if (box->pmu->type->ops->disable_box) - box->pmu->type->ops->disable_box(box); -} - -static inline void uncore_enable_box(struct intel_uncore_box *box) -{ - if (box->pmu->type->ops->enable_box) - box->pmu->type->ops->enable_box(box); -} - static inline void uncore_disable_event(struct intel_uncore_box *box, struct perf_event *event) { diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 5c056b8aebefc83468729d0a8bba6e171914c21e..e01078e93dd34f1f4ea2e9b6e4b1174c64e947f6 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -260,11 +260,21 @@ void __init hv_apic_init(void) } if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) { - pr_info("Hyper-V: Using MSR based APIC access\n"); + pr_info("Hyper-V: Using enlightened APIC (%s mode)", + x2apic_enabled() ? "x2apic" : "xapic"); + /* + * With x2apic, architectural x2apic MSRs are equivalent to the + * respective synthetic MSRs, so there's no need to override + * the apic accessors. The only exception is + * hv_apic_eoi_write, because it benefits from lazy EOI when + * available, but it works for both xapic and x2apic modes. + */ apic_set_eoi_write(hv_apic_eoi_write); - apic->read = hv_apic_read; - apic->write = hv_apic_write; - apic->icr_write = hv_apic_icr_write; - apic->icr_read = hv_apic_icr_read; + if (!x2apic_enabled()) { + apic->read = hv_apic_read; + apic->write = hv_apic_write; + apic->icr_write = hv_apic_icr_write; + apic->icr_read = hv_apic_icr_read; + } } } diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 48670eb3b4d74690443917d18410e317ccec0ed2..59bf91c57aa85d36a78d4db5b98e3f9921bbe155 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -154,6 +154,9 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit); * Workaround for the sake of BPF compilation which utilizes kernel * headers, but clang does not support ASM GOTO and fails the build. */ +#ifndef __BPF_TRACING__ +#warning "Compiler lacks ASM_GOTO support. Add -D __BPF_TRACING__ to your compiler arguments" +#endif #define static_cpu_has(bit) boot_cpu_has(bit) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 50eb430b0ad8f0733906b31691c489fb8adb53f4..24d6598dea29b2d048d41ae5c545c1366312c615 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1189,7 +1189,7 @@ struct kvm_x86_ops { int (*set_nested_state)(struct kvm_vcpu *vcpu, struct kvm_nested_state __user *user_kvm_nested_state, struct kvm_nested_state *kvm_state); - void (*get_vmcs12_pages)(struct kvm_vcpu *vcpu); + bool (*get_vmcs12_pages)(struct kvm_vcpu *vcpu); int (*smi_allowed)(struct kvm_vcpu *vcpu); int (*pre_enter_smm)(struct kvm_vcpu *vcpu, char *smstate); diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h index 8ea1cfdbeabc1d2be344e98952ab92f752738335..71b32f2570abc933429d01c4d98047c850a09563 100644 --- a/arch/x86/include/asm/sections.h +++ b/arch/x86/include/asm/sections.h @@ -13,4 +13,6 @@ extern char __end_rodata_aligned[]; extern char __end_rodata_hpage_align[]; #endif +extern char __end_of_kernel_reserve[]; + #endif /* _ASM_X86_SECTIONS_H */ diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index d3b6c3ba61d170a400949a0218cb5587befe53c5..61d93f062a36e0a567a69ee29ee7337deefa5e67 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -184,19 +184,14 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) #ifdef CONFIG_X86_32 -#define __put_user_asm_u64(x, addr, err, errret) \ - asm volatile("\n" \ - "1: movl %%eax,0(%2)\n" \ - "2: movl %%edx,4(%2)\n" \ - "3:" \ - ".section .fixup,\"ax\"\n" \ - "4: movl %3,%0\n" \ - " jmp 3b\n" \ - ".previous\n" \ - _ASM_EXTABLE_UA(1b, 4b) \ - _ASM_EXTABLE_UA(2b, 4b) \ - : "=r" (err) \ - : "A" (x), "r" (addr), "i" (errret), "0" (err)) +#define __put_user_goto_u64(x, addr, label) \ + asm_volatile_goto("\n" \ + "1: movl %%eax,0(%1)\n" \ + "2: movl %%edx,4(%1)\n" \ + _ASM_EXTABLE_UA(1b, %l2) \ + _ASM_EXTABLE_UA(2b, %l2) \ + : : "A" (x), "r" (addr) \ + : : label) #define __put_user_asm_ex_u64(x, addr) \ asm volatile("\n" \ @@ -211,8 +206,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) asm volatile("call __put_user_8" : "=a" (__ret_pu) \ : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") #else -#define __put_user_asm_u64(x, ptr, retval, errret) \ - __put_user_asm(x, ptr, retval, "q", "", "er", errret) +#define __put_user_goto_u64(x, ptr, label) \ + __put_user_goto(x, ptr, "q", "", "er", label) #define __put_user_asm_ex_u64(x, addr) \ __put_user_asm_ex(x, addr, "q", "", "er") #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) @@ -273,23 +268,21 @@ extern void __put_user_8(void); __builtin_expect(__ret_pu, 0); \ }) -#define __put_user_size(x, ptr, size, retval, errret) \ +#define __put_user_size(x, ptr, size, label) \ do { \ - retval = 0; \ __chk_user_ptr(ptr); \ switch (size) { \ case 1: \ - __put_user_asm(x, ptr, retval, "b", "b", "iq", errret); \ + __put_user_goto(x, ptr, "b", "b", "iq", label); \ break; \ case 2: \ - __put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \ + __put_user_goto(x, ptr, "w", "w", "ir", label); \ break; \ case 4: \ - __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ + __put_user_goto(x, ptr, "l", "k", "ir", label); \ break; \ case 8: \ - __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \ - errret); \ + __put_user_goto_u64(x, ptr, label); \ break; \ default: \ __put_user_bad(); \ @@ -434,9 +427,15 @@ do { \ #define __put_user_nocheck(x, ptr, size) \ ({ \ - int __pu_err; \ + __label__ __pu_label; \ + int __pu_err = -EFAULT; \ + __typeof__(*(ptr)) __pu_val = (x); \ + __typeof__(ptr) __pu_ptr = (ptr); \ + __typeof__(size) __pu_size = (size); \ __uaccess_begin(); \ - __put_user_size((x), (ptr), (size), __pu_err, -EFAULT); \ + __put_user_size(__pu_val, __pu_ptr, __pu_size, __pu_label); \ + __pu_err = 0; \ +__pu_label: \ __uaccess_end(); \ __builtin_expect(__pu_err, 0); \ }) @@ -463,17 +462,23 @@ struct __large_struct { unsigned long buf[100]; }; * we do not write to any memory gcc knows about, so there are no * aliasing issues. */ -#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ - asm volatile("\n" \ - "1: mov"itype" %"rtype"1,%2\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: mov %3,%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - _ASM_EXTABLE_UA(1b, 3b) \ - : "=r"(err) \ - : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err)) +#define __put_user_goto(x, addr, itype, rtype, ltype, label) \ + asm_volatile_goto("\n" \ + "1: mov"itype" %"rtype"0,%1\n" \ + _ASM_EXTABLE_UA(1b, %l2) \ + : : ltype(x), "m" (__m(addr)) \ + : : label) + +#define __put_user_failed(x, addr, itype, rtype, ltype, errret) \ + ({ __label__ __puflab; \ + int __pufret = errret; \ + __put_user_goto(x,addr,itype,rtype,ltype,__puflab); \ + __pufret = 0; \ + __puflab: __pufret; }) + +#define __put_user_asm(x, addr, retval, itype, rtype, ltype, errret) do { \ + retval = __put_user_failed(x, addr, itype, rtype, ltype, errret); \ +} while (0) #define __put_user_asm_ex(x, addr, itype, rtype, ltype) \ asm volatile("1: mov"itype" %"rtype"0,%1\n" \ @@ -714,16 +719,11 @@ static __must_check __always_inline bool user_access_begin(const void __user *pt #define user_access_begin(a,b) user_access_begin(a,b) #define user_access_end() __uaccess_end() -#define user_access_save() smap_save() -#define user_access_restore(x) smap_restore(x) +#define user_access_save() smap_save() +#define user_access_restore(x) smap_restore(x) -#define unsafe_put_user(x, ptr, err_label) \ -do { \ - int __pu_err; \ - __typeof__(*(ptr)) __pu_val = (x); \ - __put_user_size(__pu_val, (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \ - if (unlikely(__pu_err)) goto err_label; \ -} while (0) +#define unsafe_put_user(x, ptr, label) \ + __put_user_size((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), label) #define unsafe_get_user(x, ptr, err_label) \ do { \ diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index e00c9e87593327e781d72ff9c3b5a2545fc986c0..ac9fc51e2b1862f5dff7264a1978f3d399b5c847 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -4,6 +4,7 @@ #include #include +#include /* * The hypercall definitions differ in the low word of the %edx argument @@ -20,8 +21,8 @@ */ /* Old port-based version */ -#define VMWARE_HYPERVISOR_PORT "0x5658" -#define VMWARE_HYPERVISOR_PORT_HB "0x5659" +#define VMWARE_HYPERVISOR_PORT 0x5658 +#define VMWARE_HYPERVISOR_PORT_HB 0x5659 /* Current vmcall / vmmcall version */ #define VMWARE_HYPERVISOR_HB BIT(0) @@ -29,7 +30,8 @@ /* The low bandwidth call. The low word of edx is presumed clear. */ #define VMWARE_HYPERCALL \ - ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT ", %%dx; inl (%%dx)", \ + ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT) ", %%dx; " \ + "inl (%%dx), %%eax", \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) @@ -38,7 +40,8 @@ * HB and OUT bits set. */ #define VMWARE_HYPERCALL_HB_OUT \ - ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep outsb", \ + ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \ + "rep outsb", \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) @@ -47,7 +50,8 @@ * HB bit set. */ #define VMWARE_HYPERCALL_HB_IN \ - ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep insb", \ + ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \ + "rep insb", \ "vmcall", X86_FEATURE_VMCALL, \ "vmmcall", X86_FEATURE_VMW_VMMCALL) #endif diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 45e92cba92f52cb1627e7dc270d96abf1b0e491e..b0889c48a2ac5e02e2ff64c53b1b1f8e25cef7eb 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -156,7 +156,8 @@ static int x2apic_dead_cpu(unsigned int dead_cpu) { struct cluster_mask *cmsk = per_cpu(cluster_masks, dead_cpu); - cpumask_clear_cpu(dead_cpu, &cmsk->mask); + if (cmsk) + cpumask_clear_cpu(dead_cpu, &cmsk->mask); free_cpumask_var(per_cpu(ipi_mask, dead_cpu)); return 0; } diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 267daad8c0360890672e7db5369fde36fb58174e..c656d92cd708f8aac790968e6b38714aacdf6ecc 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -216,6 +216,10 @@ static void __init ms_hyperv_init_platform(void) int hv_host_info_ecx; int hv_host_info_edx; +#ifdef CONFIG_PARAVIRT + pv_info.name = "Hyper-V"; +#endif + /* * Extract the features and hints */ diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 29ffa495bd1cb7333b77e33aa80a055ec0ec6d69..206a4b6144c2e1d9a0780a82424c4817bf390d7d 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -222,13 +222,31 @@ unsigned long __head __startup_64(unsigned long physaddr, * we might write invalid pmds, when the kernel is relocated * cleanup_highmap() fixes this up along with the mappings * beyond _end. + * + * Only the region occupied by the kernel image has so far + * been checked against the table of usable memory regions + * provided by the firmware, so invalidate pages outside that + * region. A page table entry that maps to a reserved area of + * memory would allow processor speculation into that area, + * and on some hardware (particularly the UV platform) even + * speculative access to some reserved areas is caught as an + * error, causing the BIOS to halt the system. */ pmd = fixup_pointer(level2_kernel_pgt, physaddr); - for (i = 0; i < PTRS_PER_PMD; i++) { + + /* invalidate pages before the kernel image */ + for (i = 0; i < pmd_index((unsigned long)_text); i++) + pmd[i] &= ~_PAGE_PRESENT; + + /* fixup pages that are part of the kernel image */ + for (; i <= pmd_index((unsigned long)_end); i++) if (pmd[i] & _PAGE_PRESENT) pmd[i] += load_delta; - } + + /* invalidate pages after the kernel image */ + for (; i < PTRS_PER_PMD; i++) + pmd[i] &= ~_PAGE_PRESENT; /* * Fixup phys_base - remove the memory encryption mask to obtain diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f007d910a6e60d6e9536d71feadcd34ca5793a7a..77ea96b794bd13ac285977afc3b8e234187ef996 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -836,8 +836,14 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) void __init setup_arch(char **cmdline_p) { + /* + * Reserve the memory occupied by the kernel between _text and + * __end_of_kernel_reserve symbols. Any kernel sections after the + * __end_of_kernel_reserve symbol must be explicitly reserved with a + * separate memblock_reserve() or they will be discarded. + */ memblock_reserve(__pa_symbol(_text), - (unsigned long)__bss_stop - (unsigned long)_text); + (unsigned long)__end_of_kernel_reserve - (unsigned long)_text); /* * Make sure page 0 is always reserved because on systems with diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 4f062d33ef73415111eda82c8e2981454ecb6abc..e2feacf921a03abb949e221aafa899d4f2e042df 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -368,6 +368,14 @@ SECTIONS __bss_stop = .; } + /* + * The memory occupied from _text to here, __end_of_kernel_reserve, is + * automatically reserved in setup_arch(). Anything after here must be + * explicitly reserved using memblock_reserve() or it will be discarded + * and treated as available memory. + */ + __end_of_kernel_reserve = .; + . = ALIGN(PAGE_SIZE); .brk : AT(ADDR(.brk) - LOAD_OFFSET) { __brk_base = .; @@ -407,7 +415,6 @@ SECTIONS STABS_DEBUG DWARF_DEBUG - /* Sections to be discarded */ DISCARDS /DISCARD/ : { *(.eh_frame) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 9c5029cf6f3f245d9048599e3ff53c228f8092ec..f68c0c753c38f6fd29703f98b0646f1372969407 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -363,7 +363,7 @@ static inline void do_cpuid_7_mask(struct kvm_cpuid_entry2 *entry, int index) /* cpuid 7.0.ecx*/ const u32 kvm_cpuid_7_0_ecx_x86_features = - F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | + F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) | F(AVX512_VPOPCNTDQ) | F(UMIP) | F(AVX512_VBMI2) | F(GFNI) | F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG) | F(CLDEMOTE) | F(MOVDIRI) | F(MOVDIR64B) | 0 /*WAITPKG*/; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 87b0fcc23ef8946f7fe2f7ab46db9c0178a706b9..b29d00b661ff2155a3530bd6eeb094287a981f37 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -111,11 +111,6 @@ static inline int apic_enabled(struct kvm_lapic *apic) (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \ APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER) -static inline u8 kvm_xapic_id(struct kvm_lapic *apic) -{ - return kvm_lapic_get_reg(apic, APIC_ID) >> 24; -} - static inline u32 kvm_x2apic_id(struct kvm_lapic *apic) { return apic->vcpu->vcpu_id; diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 2aad7e226fc016e130f29746f4fa2798fb811126..1f5014852e208e1c38c9d0c7c57fa0ae8fc6d110 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -242,4 +242,9 @@ static inline enum lapic_mode kvm_apic_mode(u64 apic_base) return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); } +static inline u8 kvm_xapic_id(struct kvm_lapic *apic) +{ + return kvm_lapic_get_reg(apic, APIC_ID) >> 24; +} + #endif diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index f8ecb6df5106641517a75380e4755dfa65967f08..c5673bda4b66df5e7672abc78e5bf520b3c3361c 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -734,8 +734,14 @@ static int get_npt_level(struct kvm_vcpu *vcpu) static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) { vcpu->arch.efer = efer; - if (!npt_enabled && !(efer & EFER_LMA)) - efer &= ~EFER_LME; + + if (!npt_enabled) { + /* Shadow paging assumes NX to be available. */ + efer |= EFER_NX; + + if (!(efer & EFER_LMA)) + efer &= ~EFER_LME; + } to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME; mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR); @@ -4591,6 +4597,7 @@ static int avic_handle_ldr_update(struct kvm_vcpu *vcpu) int ret = 0; struct vcpu_svm *svm = to_svm(vcpu); u32 ldr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_LDR); + u32 id = kvm_xapic_id(vcpu->arch.apic); if (ldr == svm->ldr_reg) return 0; @@ -4598,7 +4605,7 @@ static int avic_handle_ldr_update(struct kvm_vcpu *vcpu) avic_invalidate_logical_id_entry(vcpu); if (ldr) - ret = avic_ldr_write(vcpu, vcpu->vcpu_id, ldr); + ret = avic_ldr_write(vcpu, id, ldr); if (!ret) svm->ldr_reg = ldr; @@ -4610,8 +4617,7 @@ static int avic_handle_apic_id_update(struct kvm_vcpu *vcpu) { u64 *old, *new; struct vcpu_svm *svm = to_svm(vcpu); - u32 apic_id_reg = kvm_lapic_get_reg(vcpu->arch.apic, APIC_ID); - u32 id = (apic_id_reg >> 24) & 0xff; + u32 id = kvm_xapic_id(vcpu->arch.apic); if (vcpu->vcpu_id == id) return 0; diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index e76eb4f07f6c93a2b8bad15afefbc1087d9f487c..0e7c9301fe86549e42bb2959e4408299230fb82b 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -2917,7 +2917,7 @@ static int nested_vmx_check_vmentry_hw(struct kvm_vcpu *vcpu) static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12); -static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) +static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) { struct vmcs12 *vmcs12 = get_vmcs12(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -2937,19 +2937,18 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) vmx->nested.apic_access_page = NULL; } page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->apic_access_addr); - /* - * If translation failed, no matter: This feature asks - * to exit when accessing the given address, and if it - * can never be accessed, this feature won't do - * anything anyway. - */ if (!is_error_page(page)) { vmx->nested.apic_access_page = page; hpa = page_to_phys(vmx->nested.apic_access_page); vmcs_write64(APIC_ACCESS_ADDR, hpa); } else { - secondary_exec_controls_clearbit(vmx, - SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES); + pr_debug_ratelimited("%s: no backing 'struct page' for APIC-access address in vmcs12\n", + __func__); + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->internal.suberror = + KVM_INTERNAL_ERROR_EMULATION; + vcpu->run->internal.ndata = 0; + return false; } } @@ -2994,6 +2993,7 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) exec_controls_setbit(vmx, CPU_BASED_USE_MSR_BITMAPS); else exec_controls_clearbit(vmx, CPU_BASED_USE_MSR_BITMAPS); + return true; } /* @@ -3032,13 +3032,15 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, /* * If from_vmentry is false, this is being called from state restore (either RSM * or KVM_SET_NESTED_STATE). Otherwise it's called from vmlaunch/vmresume. -+ * -+ * Returns: -+ * 0 - success, i.e. proceed with actual VMEnter -+ * 1 - consistency check VMExit -+ * -1 - consistency check VMFail + * + * Returns: + * NVMX_ENTRY_SUCCESS: Entered VMX non-root mode + * NVMX_ENTRY_VMFAIL: Consistency check VMFail + * NVMX_ENTRY_VMEXIT: Consistency check VMExit + * NVMX_ENTRY_KVM_INTERNAL_ERROR: KVM internal error */ -int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry) +enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, + bool from_vmentry) { struct vcpu_vmx *vmx = to_vmx(vcpu); struct vmcs12 *vmcs12 = get_vmcs12(vcpu); @@ -3081,11 +3083,12 @@ int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry) prepare_vmcs02_early(vmx, vmcs12); if (from_vmentry) { - nested_get_vmcs12_pages(vcpu); + if (unlikely(!nested_get_vmcs12_pages(vcpu))) + return NVMX_VMENTRY_KVM_INTERNAL_ERROR; if (nested_vmx_check_vmentry_hw(vcpu)) { vmx_switch_vmcs(vcpu, &vmx->vmcs01); - return -1; + return NVMX_VMENTRY_VMFAIL; } if (nested_vmx_check_guest_state(vcpu, vmcs12, &exit_qual)) @@ -3149,7 +3152,7 @@ int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry) * returned as far as L1 is concerned. It will only return (and set * the success flag) when L2 exits (see nested_vmx_vmexit()). */ - return 0; + return NVMX_VMENTRY_SUCCESS; /* * A failed consistency check that leads to a VMExit during L1's @@ -3165,14 +3168,14 @@ int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry) vmx_switch_vmcs(vcpu, &vmx->vmcs01); if (!from_vmentry) - return 1; + return NVMX_VMENTRY_VMEXIT; load_vmcs12_host_state(vcpu, vmcs12); vmcs12->vm_exit_reason = exit_reason | VMX_EXIT_REASONS_FAILED_VMENTRY; vmcs12->exit_qualification = exit_qual; if (enable_shadow_vmcs || vmx->nested.hv_evmcs) vmx->nested.need_vmcs12_to_shadow_sync = true; - return 1; + return NVMX_VMENTRY_VMEXIT; } /* @@ -3182,9 +3185,9 @@ int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry) static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) { struct vmcs12 *vmcs12; + enum nvmx_vmentry_status status; struct vcpu_vmx *vmx = to_vmx(vcpu); u32 interrupt_shadow = vmx_get_interrupt_shadow(vcpu); - int ret; if (!nested_vmx_check_permission(vcpu)) return 1; @@ -3244,13 +3247,9 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) * the nested entry. */ vmx->nested.nested_run_pending = 1; - ret = nested_vmx_enter_non_root_mode(vcpu, true); - vmx->nested.nested_run_pending = !ret; - if (ret > 0) - return 1; - else if (ret) - return nested_vmx_failValid(vcpu, - VMXERR_ENTRY_INVALID_CONTROL_FIELD); + status = nested_vmx_enter_non_root_mode(vcpu, true); + if (unlikely(status != NVMX_VMENTRY_SUCCESS)) + goto vmentry_failed; /* Hide L1D cache contents from the nested guest. */ vmx->vcpu.arch.l1tf_flush_l1d = true; @@ -3281,6 +3280,15 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) return kvm_vcpu_halt(vcpu); } return 1; + +vmentry_failed: + vmx->nested.nested_run_pending = 0; + if (status == NVMX_VMENTRY_KVM_INTERNAL_ERROR) + return 0; + if (status == NVMX_VMENTRY_VMEXIT) + return 1; + WARN_ON_ONCE(status != NVMX_VMENTRY_VMFAIL); + return nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); } /* diff --git a/arch/x86/kvm/vmx/nested.h b/arch/x86/kvm/vmx/nested.h index 187d39bf0bf10ca178cc3f1a7b45e18b7000ccbe..6280f33e5fa604c745ac19f3e62fda681709c90d 100644 --- a/arch/x86/kvm/vmx/nested.h +++ b/arch/x86/kvm/vmx/nested.h @@ -6,6 +6,16 @@ #include "vmcs12.h" #include "vmx.h" +/* + * Status returned by nested_vmx_enter_non_root_mode(): + */ +enum nvmx_vmentry_status { + NVMX_VMENTRY_SUCCESS, /* Entered VMX non-root mode */ + NVMX_VMENTRY_VMFAIL, /* Consistency check VMFail */ + NVMX_VMENTRY_VMEXIT, /* Consistency check VMExit */ + NVMX_VMENTRY_KVM_INTERNAL_ERROR,/* KVM internal error */ +}; + void vmx_leave_nested(struct kvm_vcpu *vcpu); void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps, bool apicv); @@ -13,7 +23,8 @@ void nested_vmx_hardware_unsetup(void); __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *)); void nested_vmx_vcpu_setup(void); void nested_vmx_free_vcpu(struct kvm_vcpu *vcpu); -int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry); +enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, + bool from_vmentry); bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason); void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, u32 exit_intr_info, unsigned long exit_qualification); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index e7970a2e8eae918f76ce8ef3646aba0f39a27275..5d21a4ab28cfc80b3f800adfd042cb23c155a737 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -969,17 +969,9 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset) u64 guest_efer = vmx->vcpu.arch.efer; u64 ignore_bits = 0; - if (!enable_ept) { - /* - * NX is needed to handle CR0.WP=1, CR4.SMEP=1. Testing - * host CPUID is more efficient than testing guest CPUID - * or CR4. Host SMEP is anyway a requirement for guest SMEP. - */ - if (boot_cpu_has(X86_FEATURE_SMEP)) - guest_efer |= EFER_NX; - else if (!(guest_efer & EFER_NX)) - ignore_bits |= EFER_NX; - } + /* Shadow paging assumes NX to be available. */ + if (!enable_ept) + guest_efer |= EFER_NX; /* * LMA and LME handled by hardware; SCE meaningless outside long mode. @@ -5543,14 +5535,6 @@ static int handle_encls(struct kvm_vcpu *vcpu) return 1; } -static int handle_unexpected_vmexit(struct kvm_vcpu *vcpu) -{ - kvm_skip_emulated_instruction(vcpu); - WARN_ONCE(1, "Unexpected VM-Exit Reason = 0x%x", - vmcs_read32(VM_EXIT_REASON)); - return 1; -} - /* * The exit handlers return 1 if the exit was handled fully and guest execution * may resume. Otherwise they set the kvm_run parameter to indicate what needs @@ -5602,15 +5586,11 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { [EXIT_REASON_INVVPID] = handle_vmx_instruction, [EXIT_REASON_RDRAND] = handle_invalid_op, [EXIT_REASON_RDSEED] = handle_invalid_op, - [EXIT_REASON_XSAVES] = handle_unexpected_vmexit, - [EXIT_REASON_XRSTORS] = handle_unexpected_vmexit, [EXIT_REASON_PML_FULL] = handle_pml_full, [EXIT_REASON_INVPCID] = handle_invpcid, [EXIT_REASON_VMFUNC] = handle_vmx_instruction, [EXIT_REASON_PREEMPTION_TIMER] = handle_preemption_timer, [EXIT_REASON_ENCLS] = handle_encls, - [EXIT_REASON_UMWAIT] = handle_unexpected_vmexit, - [EXIT_REASON_TPAUSE] = handle_unexpected_vmexit, }; static const int kvm_vmx_max_exit_handlers = diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 661e2bf3852664c63c95b34360712a7bf8674521..ff395f8127190b10986ec116eac85b30f379ab8c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -360,8 +360,7 @@ EXPORT_SYMBOL_GPL(kvm_set_apic_base); asmlinkage __visible void kvm_spurious_fault(void) { /* Fault while not rebooting. We want the trace. */ - if (!kvm_rebooting) - BUG(); + BUG_ON(!kvm_rebooting); } EXPORT_SYMBOL_GPL(kvm_spurious_fault); @@ -2537,6 +2536,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data) static void kvmclock_reset(struct kvm_vcpu *vcpu) { vcpu->arch.pv_time_enabled = false; + vcpu->arch.time = 0; } static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa) @@ -2702,8 +2702,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_KVM_SYSTEM_TIME: { struct kvm_arch *ka = &vcpu->kvm->arch; - kvmclock_reset(vcpu); - if (vcpu->vcpu_id == 0 && !msr_info->host_initiated) { bool tmp = (msr == MSR_KVM_SYSTEM_TIME); @@ -2717,14 +2715,13 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) kvm_make_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu); /* we verify if the enable bit is set... */ + vcpu->arch.pv_time_enabled = false; if (!(data & 1)) break; - if (kvm_gfn_to_hva_cache_init(vcpu->kvm, + if (!kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_time, data & ~1ULL, sizeof(struct pvclock_vcpu_time_info))) - vcpu->arch.pv_time_enabled = false; - else vcpu->arch.pv_time_enabled = true; break; @@ -7941,8 +7938,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) bool req_immediate_exit = false; if (kvm_request_pending(vcpu)) { - if (kvm_check_request(KVM_REQ_GET_VMCS12_PAGES, vcpu)) - kvm_x86_ops->get_vmcs12_pages(vcpu); + if (kvm_check_request(KVM_REQ_GET_VMCS12_PAGES, vcpu)) { + if (unlikely(!kvm_x86_ops->get_vmcs12_pages(vcpu))) { + r = 0; + goto out; + } + } if (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu)) kvm_mmu_unload(vcpu); if (kvm_check_request(KVM_REQ_MIGRATE_TIMER, vcpu)) diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 58f79ab32358429ea4f948ccccbdfe86e9e294e3..5bfea374a1609a590d9cae7b343b07f85e02bf6d 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -117,6 +117,14 @@ static void __init xen_banner(void) printk(KERN_INFO "Xen version: %d.%d%s%s\n", version >> 16, version & 0xffff, extra.extraversion, xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); + +#ifdef CONFIG_X86_32 + pr_warn("WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!\n" + "Support for running as 32-bit PV-guest under Xen will soon be removed\n" + "from the Linux kernel!\n" + "Please use either a 64-bit kernel or switch to HVM or PVH mode!\n" + "WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!\n"); +#endif } static void __init xen_pv_init_platform(void) diff --git a/arch/xtensa/boot/dts/virt.dts b/arch/xtensa/boot/dts/virt.dts index a9dcd87b6eb1ee894fc540d173dcd77030ed54da..611b98a02a65e858bae4e5f9815a36eeab3c285c 100644 --- a/arch/xtensa/boot/dts/virt.dts +++ b/arch/xtensa/boot/dts/virt.dts @@ -56,7 +56,7 @@ reg = <0xf0100000 0x03f00000>; // BUS_ADDRESS(3) CPU_PHYSICAL(1) SIZE(2) - ranges = <0x01000000 0x0 0xf0000000 0xf0000000 0x0 0x00010000>, + ranges = <0x01000000 0x0 0x00000000 0xf0000000 0x0 0x00010000>, <0x02000000 0x0 0xf4000000 0xf4000000 0x0 0x08000000>; // PCI_DEVICE(3) INT#(1) CONTROLLER(PHANDLE) CONTROLLER_DATA(2) diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h index aeb15f4c755b379de5d0c0f62eba6eaab7d7229e..be8b2be5a98bd9b8972b88630d2ca978fe3130cc 100644 --- a/arch/xtensa/include/asm/bitops.h +++ b/arch/xtensa/include/asm/bitops.h @@ -148,7 +148,7 @@ static inline void change_bit(unsigned int bit, volatile unsigned long *p) " getex %0\n" " beqz %0, 1b\n" : "=&a" (tmp) - : "a" (~mask), "a" (p) + : "a" (mask), "a" (p) : "memory"); } diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index 6792928ba84a7bb16d20a661f5070d0676e2f6b6..3f80386f18838902b1a96a32c3839cf9979ec436 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -100,7 +100,7 @@ do { \ case 4: __put_user_asm(x, ptr, retval, 4, "s32i", __cb); break; \ case 8: { \ __typeof__(*ptr) __v64 = x; \ - retval = __copy_to_user(ptr, &__v64, 8); \ + retval = __copy_to_user(ptr, &__v64, 8) ? -EFAULT : 0; \ break; \ } \ default: __put_user_bad(); \ @@ -132,14 +132,14 @@ do { \ #define __check_align_1 "" #define __check_align_2 \ - " _bbci.l %3, 0, 1f \n" \ - " movi %0, %4 \n" \ + " _bbci.l %[addr], 0, 1f \n" \ + " movi %[err], %[efault] \n" \ " _j 2f \n" #define __check_align_4 \ - " _bbsi.l %3, 0, 0f \n" \ - " _bbci.l %3, 1, 1f \n" \ - "0: movi %0, %4 \n" \ + " _bbsi.l %[addr], 0, 0f \n" \ + " _bbci.l %[addr], 1, 1f \n" \ + "0: movi %[err], %[efault] \n" \ " _j 2f \n" @@ -151,40 +151,40 @@ do { \ * WARNING: If you modify this macro at all, verify that the * __check_align_* macros still work. */ -#define __put_user_asm(x, addr, err, align, insn, cb) \ +#define __put_user_asm(x_, addr_, err_, align, insn, cb)\ __asm__ __volatile__( \ __check_align_##align \ - "1: "insn" %2, %3, 0 \n" \ + "1: "insn" %[x], %[addr], 0 \n" \ "2: \n" \ " .section .fixup,\"ax\" \n" \ " .align 4 \n" \ " .literal_position \n" \ "5: \n" \ - " movi %1, 2b \n" \ - " movi %0, %4 \n" \ - " jx %1 \n" \ + " movi %[tmp], 2b \n" \ + " movi %[err], %[efault] \n" \ + " jx %[tmp] \n" \ " .previous \n" \ " .section __ex_table,\"a\" \n" \ " .long 1b, 5b \n" \ " .previous" \ - :"=r" (err), "=r" (cb) \ - :"r" ((int)(x)), "r" (addr), "i" (-EFAULT), "0" (err)) + :[err] "+r"(err_), [tmp] "=r"(cb) \ + :[x] "r"(x_), [addr] "r"(addr_), [efault] "i"(-EFAULT)) #define __get_user_nocheck(x, ptr, size) \ ({ \ - long __gu_err, __gu_val; \ - __get_user_size(__gu_val, (ptr), (size), __gu_err); \ - (x) = (__force __typeof__(*(ptr)))__gu_val; \ + long __gu_err; \ + __get_user_size((x), (ptr), (size), __gu_err); \ __gu_err; \ }) #define __get_user_check(x, ptr, size) \ ({ \ - long __gu_err = -EFAULT, __gu_val = 0; \ + long __gu_err = -EFAULT; \ const __typeof__(*(ptr)) *__gu_addr = (ptr); \ - if (access_ok(__gu_addr, size)) \ - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ - (x) = (__force __typeof__(*(ptr)))__gu_val; \ + if (access_ok(__gu_addr, size)) \ + __get_user_size((x), __gu_addr, (size), __gu_err); \ + else \ + (x) = 0; \ __gu_err; \ }) @@ -198,8 +198,17 @@ do { \ case 1: __get_user_asm(x, ptr, retval, 1, "l8ui", __cb); break;\ case 2: __get_user_asm(x, ptr, retval, 2, "l16ui", __cb); break;\ case 4: __get_user_asm(x, ptr, retval, 4, "l32i", __cb); break;\ - case 8: retval = __copy_from_user(&x, ptr, 8); break; \ - default: (x) = __get_user_bad(); \ + case 8: { \ + u64 __x; \ + if (unlikely(__copy_from_user(&__x, ptr, 8))) { \ + retval = -EFAULT; \ + (x) = 0; \ + } else { \ + (x) = *(__force __typeof__((ptr)))&__x; \ + } \ + break; \ + } \ + default: (x) = 0; __get_user_bad(); \ } \ } while (0) @@ -208,25 +217,28 @@ do { \ * WARNING: If you modify this macro at all, verify that the * __check_align_* macros still work. */ -#define __get_user_asm(x, addr, err, align, insn, cb) \ -__asm__ __volatile__( \ - __check_align_##align \ - "1: "insn" %2, %3, 0 \n" \ - "2: \n" \ - " .section .fixup,\"ax\" \n" \ - " .align 4 \n" \ - " .literal_position \n" \ - "5: \n" \ - " movi %1, 2b \n" \ - " movi %2, 0 \n" \ - " movi %0, %4 \n" \ - " jx %1 \n" \ - " .previous \n" \ - " .section __ex_table,\"a\" \n" \ - " .long 1b, 5b \n" \ - " .previous" \ - :"=r" (err), "=r" (cb), "=r" (x) \ - :"r" (addr), "i" (-EFAULT), "0" (err)) +#define __get_user_asm(x_, addr_, err_, align, insn, cb) \ +do { \ + u32 __x = 0; \ + __asm__ __volatile__( \ + __check_align_##align \ + "1: "insn" %[x], %[addr], 0 \n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + " .align 4 \n" \ + " .literal_position \n" \ + "5: \n" \ + " movi %[tmp], 2b \n" \ + " movi %[err], %[efault] \n" \ + " jx %[tmp] \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " .long 1b, 5b \n" \ + " .previous" \ + :[err] "+r"(err_), [tmp] "=r"(cb), [x] "+r"(__x) \ + :[addr] "r"(addr_), [efault] "i"(-EFAULT)); \ + (x_) = (__force __typeof__(*(addr_)))__x; \ +} while (0) /* diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 04f19de4670033142537a6271b749c30836ea47e..4092555828b13a25305f250863ad2e4d42016727 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -119,13 +119,6 @@ EXPORT_SYMBOL(__invalidate_icache_range); // FIXME EXPORT_SYMBOL(screen_info); #endif -EXPORT_SYMBOL(outsb); -EXPORT_SYMBOL(outsw); -EXPORT_SYMBOL(outsl); -EXPORT_SYMBOL(insb); -EXPORT_SYMBOL(insw); -EXPORT_SYMBOL(insl); - extern long common_exception_return; EXPORT_SYMBOL(common_exception_return); diff --git a/block/Kconfig b/block/Kconfig index 41c0917ce6223db176ccf5922186465e12abebef..606a67e47e6891e838e47acd072acef38cd16a7d 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -177,6 +177,16 @@ config BLK_SED_OPAL Enabling this option enables users to setup/unlock/lock Locking ranges for SED devices using the Opal protocol. +config BLK_INLINE_ENCRYPTION + bool "Enable inline encryption support in block layer" + select CRYPTO + select CRYPTO_BLKCIPHER + help + Build the blk-crypto subsystem. + Enabling this lets the block layer handle encryption, + so users can take advantage of inline encryption + hardware if present. + menu "Partition Types" source "block/partitions/Kconfig" diff --git a/block/Makefile b/block/Makefile index 9ef57ace90d46c1cd6544369a80b802896ce99c9..8932c7e4fd0737d36c978e78b90fa97d875b672a 100644 --- a/block/Makefile +++ b/block/Makefile @@ -36,3 +36,5 @@ obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o obj-$(CONFIG_BLK_PM) += blk-pm.o +obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += keyslot-manager.o bio-crypt-ctx.o \ + blk-crypto.o diff --git a/block/bio-crypt-ctx.c b/block/bio-crypt-ctx.c new file mode 100644 index 0000000000000000000000000000000000000000..0f7641b875e923246269ac424d141bfa4513eac9 --- /dev/null +++ b/block/bio-crypt-ctx.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include +#include +#include +#include + +static int num_prealloc_crypt_ctxs = 128; +static struct kmem_cache *bio_crypt_ctx_cache; +static mempool_t *bio_crypt_ctx_pool; + +int bio_crypt_ctx_init(void) +{ + bio_crypt_ctx_cache = KMEM_CACHE(bio_crypt_ctx, 0); + if (!bio_crypt_ctx_cache) + return -ENOMEM; + + bio_crypt_ctx_pool = mempool_create_slab_pool( + num_prealloc_crypt_ctxs, + bio_crypt_ctx_cache); + + if (!bio_crypt_ctx_pool) + return -ENOMEM; + + return 0; +} + +struct bio_crypt_ctx *bio_crypt_alloc_ctx(gfp_t gfp_mask) +{ + return mempool_alloc(bio_crypt_ctx_pool, gfp_mask); +} +EXPORT_SYMBOL(bio_crypt_alloc_ctx); + +void bio_crypt_free_ctx(struct bio *bio) +{ + mempool_free(bio->bi_crypt_context, bio_crypt_ctx_pool); + bio->bi_crypt_context = NULL; +} +EXPORT_SYMBOL(bio_crypt_free_ctx); + +int bio_crypt_clone(struct bio *dst, struct bio *src, gfp_t gfp_mask) +{ + /* + * If a bio is swhandled, then it will be decrypted when bio_endio + * is called. As we only want the data to be decrypted once, copies + * of the bio must not have have a crypt context. + */ + if (!bio_has_crypt_ctx(src) || bio_crypt_swhandled(src)) + return 0; + + dst->bi_crypt_context = bio_crypt_alloc_ctx(gfp_mask); + if (!dst->bi_crypt_context) + return -ENOMEM; + + *dst->bi_crypt_context = *src->bi_crypt_context; + + if (bio_crypt_has_keyslot(src)) + keyslot_manager_get_slot(src->bi_crypt_context->processing_ksm, + src->bi_crypt_context->keyslot); + + return 0; +} +EXPORT_SYMBOL(bio_crypt_clone); + +bool bio_crypt_should_process(struct bio *bio, struct request_queue *q) +{ + if (!bio_has_crypt_ctx(bio)) + return false; + + if (q->ksm != bio->bi_crypt_context->processing_ksm) + return false; + + WARN_ON(!bio_crypt_has_keyslot(bio)); + return true; +} +EXPORT_SYMBOL(bio_crypt_should_process); + +/* + * Checks that two bio crypt contexts are compatible - i.e. that + * they are mergeable except for data_unit_num continuity. + */ +bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2) +{ + struct bio_crypt_ctx *bc1 = b_1->bi_crypt_context; + struct bio_crypt_ctx *bc2 = b_2->bi_crypt_context; + + if (bio_has_crypt_ctx(b_1) != bio_has_crypt_ctx(b_2)) + return false; + + if (!bio_has_crypt_ctx(b_1)) + return true; + + return bc1->keyslot == bc2->keyslot && + bc1->data_unit_size_bits == bc2->data_unit_size_bits; +} + +/* + * Checks that two bio crypt contexts are compatible, and also + * that their data_unit_nums are continuous (and can hence be merged) + */ +bool bio_crypt_ctx_back_mergeable(struct bio *b_1, + unsigned int b1_sectors, + struct bio *b_2) +{ + struct bio_crypt_ctx *bc1 = b_1->bi_crypt_context; + struct bio_crypt_ctx *bc2 = b_2->bi_crypt_context; + + if (!bio_crypt_ctx_compatible(b_1, b_2)) + return false; + + return !bio_has_crypt_ctx(b_1) || + (bc1->data_unit_num + + (b1_sectors >> (bc1->data_unit_size_bits - 9)) == + bc2->data_unit_num); +} + +void bio_crypt_ctx_release_keyslot(struct bio *bio) +{ + struct bio_crypt_ctx *crypt_ctx = bio->bi_crypt_context; + + keyslot_manager_put_slot(crypt_ctx->processing_ksm, crypt_ctx->keyslot); + bio->bi_crypt_context->processing_ksm = NULL; + bio->bi_crypt_context->keyslot = -1; +} + +int bio_crypt_ctx_acquire_keyslot(struct bio *bio, struct keyslot_manager *ksm) +{ + int slot; + enum blk_crypto_mode_num crypto_mode = bio_crypto_mode(bio); + + if (!ksm) + return -ENOMEM; + + slot = keyslot_manager_get_slot_for_key(ksm, + bio_crypt_raw_key(bio), crypto_mode, + 1 << bio->bi_crypt_context->data_unit_size_bits); + if (slot < 0) + return slot; + + bio_crypt_set_keyslot(bio, slot, ksm); + return 0; +} diff --git a/block/bio.c b/block/bio.c index 8f0ed6228fc59494c6319b3f50a26ba49669a221..36a1712328d0e7bb0b02221ac2726ab15e262e69 100644 --- a/block/bio.c +++ b/block/bio.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "blk.h" @@ -241,6 +242,7 @@ static void bio_free(struct bio *bio) struct bio_set *bs = bio->bi_pool; void *p; + bio_crypt_free_ctx(bio); bio_uninit(bio); if (bs) { @@ -612,15 +614,15 @@ struct bio *bio_clone_fast(struct bio *bio, gfp_t gfp_mask, struct bio_set *bs) __bio_clone_fast(b, bio); - if (bio_integrity(bio)) { - int ret; - - ret = bio_integrity_clone(b, bio, gfp_mask); + if (bio_crypt_clone(b, bio, gfp_mask) < 0) { + bio_put(b); + return NULL; + } - if (ret < 0) { - bio_put(b); - return NULL; - } + if (bio_integrity(bio) && + bio_integrity_clone(b, bio, gfp_mask) < 0) { + bio_put(b); + return NULL; } return b; @@ -992,6 +994,7 @@ void bio_advance(struct bio *bio, unsigned bytes) if (bio_integrity(bio)) bio_integrity_advance(bio, bytes); + bio_crypt_advance(bio, bytes); bio_advance_iter(bio, &bio->bi_iter, bytes); } EXPORT_SYMBOL(bio_advance); @@ -1786,6 +1789,10 @@ void bio_endio(struct bio *bio) again: if (!bio_remaining_done(bio)) return; + + if (!blk_crypto_endio(bio)) + return; + if (!bio_integrity_endio(bio)) return; diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index b6f20be0fc78c16a2984294386a25b2893f677fc..5d21027b1faf03b1a16bcd38b8670657c9f02380 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -1362,7 +1362,7 @@ int blkcg_activate_policy(struct request_queue *q, const struct blkcg_policy *pol) { struct blkg_policy_data *pd_prealloc = NULL; - struct blkcg_gq *blkg; + struct blkcg_gq *blkg, *pinned_blkg = NULL; int ret; if (blkcg_policy_enabled(q, pol)) @@ -1370,49 +1370,82 @@ int blkcg_activate_policy(struct request_queue *q, if (queue_is_mq(q)) blk_mq_freeze_queue(q); -pd_prealloc: - if (!pd_prealloc) { - pd_prealloc = pol->pd_alloc_fn(GFP_KERNEL, q, &blkcg_root); - if (!pd_prealloc) { - ret = -ENOMEM; - goto out_bypass_end; - } - } - +retry: spin_lock_irq(&q->queue_lock); - /* blkg_list is pushed at the head, reverse walk to init parents first */ + /* blkg_list is pushed at the head, reverse walk to allocate parents first */ list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) { struct blkg_policy_data *pd; if (blkg->pd[pol->plid]) continue; - pd = pol->pd_alloc_fn(GFP_NOWAIT | __GFP_NOWARN, q, &blkcg_root); - if (!pd) - swap(pd, pd_prealloc); + /* If prealloc matches, use it; otherwise try GFP_NOWAIT */ + if (blkg == pinned_blkg) { + pd = pd_prealloc; + pd_prealloc = NULL; + } else { + pd = pol->pd_alloc_fn(GFP_NOWAIT | __GFP_NOWARN, q, + blkg->blkcg); + } + if (!pd) { + /* + * GFP_NOWAIT failed. Free the existing one and + * prealloc for @blkg w/ GFP_KERNEL. + */ + if (pinned_blkg) + blkg_put(pinned_blkg); + blkg_get(blkg); + pinned_blkg = blkg; + spin_unlock_irq(&q->queue_lock); - goto pd_prealloc; + + if (pd_prealloc) + pol->pd_free_fn(pd_prealloc); + pd_prealloc = pol->pd_alloc_fn(GFP_KERNEL, q, + blkg->blkcg); + if (pd_prealloc) + goto retry; + else + goto enomem; } blkg->pd[pol->plid] = pd; pd->blkg = blkg; pd->plid = pol->plid; - if (pol->pd_init_fn) - pol->pd_init_fn(pd); } + /* all allocated, init in the same order */ + if (pol->pd_init_fn) + list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) + pol->pd_init_fn(blkg->pd[pol->plid]); + __set_bit(pol->plid, q->blkcg_pols); ret = 0; spin_unlock_irq(&q->queue_lock); -out_bypass_end: +out: if (queue_is_mq(q)) blk_mq_unfreeze_queue(q); + if (pinned_blkg) + blkg_put(pinned_blkg); if (pd_prealloc) pol->pd_free_fn(pd_prealloc); return ret; + +enomem: + /* alloc failed, nothing's initialized yet, free everything */ + spin_lock_irq(&q->queue_lock); + list_for_each_entry(blkg, &q->blkg_list, q_node) { + if (blkg->pd[pol->plid]) { + pol->pd_free_fn(blkg->pd[pol->plid]); + blkg->pd[pol->plid] = NULL; + } + } + spin_unlock_irq(&q->queue_lock); + ret = -ENOMEM; + goto out; } EXPORT_SYMBOL_GPL(blkcg_activate_policy); diff --git a/block/blk-core.c b/block/blk-core.c index d5e668ec751b50f8cbdba497108e6f46a4a2409a..0f7e81dbe2ee94bf5a90d85143d47878a6e83df0 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -38,6 +38,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -1061,7 +1062,9 @@ blk_qc_t generic_make_request(struct bio *bio) /* Create a fresh bio_list for all subordinate requests */ bio_list_on_stack[1] = bio_list_on_stack[0]; bio_list_init(&bio_list_on_stack[0]); - ret = q->make_request_fn(q, bio); + + if (!blk_crypto_submit_bio(&bio)) + ret = q->make_request_fn(q, bio); blk_queue_exit(q); @@ -1114,6 +1117,9 @@ blk_qc_t direct_make_request(struct bio *bio) if (!generic_make_request_checks(bio)) return BLK_QC_T_NONE; + if (blk_crypto_submit_bio(&bio)) + return BLK_QC_T_NONE; + if (unlikely(blk_queue_enter(q, nowait ? BLK_MQ_REQ_NOWAIT : 0))) { if (nowait && !blk_queue_dying(q)) bio->bi_status = BLK_STS_AGAIN; @@ -1807,5 +1813,11 @@ int __init blk_dev_init(void) blk_debugfs_root = debugfs_create_dir("block", NULL); #endif + if (bio_crypt_ctx_init() < 0) + panic("Failed to allocate mem for bio crypt ctxs\n"); + + if (blk_crypto_init() < 0) + panic("Failed to init blk-crypto\n"); + return 0; } diff --git a/block/blk-crypto.c b/block/blk-crypto.c new file mode 100644 index 0000000000000000000000000000000000000000..89649655bf4b5985c248fe43c684e8c425a34b33 --- /dev/null +++ b/block/blk-crypto.c @@ -0,0 +1,798 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +/* + * Refer to Documentation/block/inline-encryption.rst for detailed explanation. + */ + +#define pr_fmt(fmt) "blk-crypto: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Represents a crypto mode supported by blk-crypto */ +struct blk_crypto_mode { + const char *cipher_str; /* crypto API name (for fallback case) */ + size_t keysize; /* key size in bytes */ +}; + +static const struct blk_crypto_mode blk_crypto_modes[] = { + [BLK_ENCRYPTION_MODE_AES_256_XTS] = { + .cipher_str = "xts(aes)", + .keysize = 64, + }, +}; + +static unsigned int num_prealloc_bounce_pg = 32; +module_param(num_prealloc_bounce_pg, uint, 0); +MODULE_PARM_DESC(num_prealloc_bounce_pg, + "Number of preallocated bounce pages for blk-crypto to use during crypto API fallback encryption"); + +#define BLK_CRYPTO_MAX_KEY_SIZE 64 +static int blk_crypto_num_keyslots = 100; +module_param_named(num_keyslots, blk_crypto_num_keyslots, int, 0); +MODULE_PARM_DESC(num_keyslots, + "Number of keyslots for crypto API fallback in blk-crypto."); + +static struct blk_crypto_keyslot { + struct crypto_skcipher *tfm; + enum blk_crypto_mode_num crypto_mode; + u8 key[BLK_CRYPTO_MAX_KEY_SIZE]; + struct crypto_skcipher *tfms[ARRAY_SIZE(blk_crypto_modes)]; +} *blk_crypto_keyslots; + +/* + * Allocating a crypto tfm during I/O can deadlock, so we have to preallocate + * all of a mode's tfms when that mode starts being used. Since each mode may + * need all the keyslots at some point, each mode needs its own tfm for each + * keyslot; thus, a keyslot may contain tfms for multiple modes. However, to + * match the behavior of real inline encryption hardware (which only supports a + * single encryption context per keyslot), we only allow one tfm per keyslot to + * be used at a time - the rest of the unused tfms have their keys cleared. + */ +static struct mutex tfms_lock[ARRAY_SIZE(blk_crypto_modes)]; +static bool tfms_inited[ARRAY_SIZE(blk_crypto_modes)]; + +struct work_mem { + struct work_struct crypto_work; + struct bio *bio; +}; + +/* The following few vars are only used during the crypto API fallback */ +static struct keyslot_manager *blk_crypto_ksm; +static struct workqueue_struct *blk_crypto_wq; +static mempool_t *blk_crypto_page_pool; +static struct kmem_cache *blk_crypto_work_mem_cache; + +bool bio_crypt_swhandled(struct bio *bio) +{ + return bio_has_crypt_ctx(bio) && + bio->bi_crypt_context->processing_ksm == blk_crypto_ksm; +} + +static u8 blank_key[BLK_CRYPTO_MAX_KEY_SIZE]; +static void evict_keyslot(unsigned int slot) +{ + struct blk_crypto_keyslot *slotp = &blk_crypto_keyslots[slot]; + enum blk_crypto_mode_num crypto_mode = slotp->crypto_mode; + int err; + + WARN_ON(slotp->crypto_mode == BLK_ENCRYPTION_MODE_INVALID); + + /* Clear the key in the skcipher */ + err = crypto_skcipher_setkey(slotp->tfms[crypto_mode], blank_key, + blk_crypto_modes[crypto_mode].keysize); + WARN_ON(err); + memzero_explicit(slotp->key, BLK_CRYPTO_MAX_KEY_SIZE); + slotp->crypto_mode = BLK_ENCRYPTION_MODE_INVALID; +} + +static int blk_crypto_keyslot_program(void *priv, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size, + unsigned int slot) +{ + struct blk_crypto_keyslot *slotp = &blk_crypto_keyslots[slot]; + const struct blk_crypto_mode *mode = &blk_crypto_modes[crypto_mode]; + size_t keysize = mode->keysize; + int err; + + if (crypto_mode != slotp->crypto_mode && + slotp->crypto_mode != BLK_ENCRYPTION_MODE_INVALID) { + evict_keyslot(slot); + } + + if (!slotp->tfms[crypto_mode]) + return -ENOMEM; + slotp->crypto_mode = crypto_mode; + err = crypto_skcipher_setkey(slotp->tfms[crypto_mode], key, keysize); + + if (err) { + evict_keyslot(slot); + return err; + } + + memcpy(slotp->key, key, keysize); + + return 0; +} + +static int blk_crypto_keyslot_evict(void *priv, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size, + unsigned int slot) +{ + evict_keyslot(slot); + return 0; +} + +static int blk_crypto_keyslot_find(void *priv, + const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size_bytes) +{ + int slot; + const size_t keysize = blk_crypto_modes[crypto_mode].keysize; + + for (slot = 0; slot < blk_crypto_num_keyslots; slot++) { + if (blk_crypto_keyslots[slot].crypto_mode == crypto_mode && + !crypto_memneq(blk_crypto_keyslots[slot].key, key, keysize)) + return slot; + } + + return -ENOKEY; +} + +static bool blk_crypto_mode_supported(void *priv, + enum blk_crypto_mode_num crypt_mode, + unsigned int data_unit_size) +{ + /* All blk_crypto_modes are required to have a crypto API fallback. */ + return true; +} + +/* + * The crypto API fallback KSM ops - only used for a bio when it specifies a + * blk_crypto_mode for which we failed to get a keyslot in the device's inline + * encryption hardware (which probably means the device doesn't have inline + * encryption hardware that supports that crypto mode). + */ +static const struct keyslot_mgmt_ll_ops blk_crypto_ksm_ll_ops = { + .keyslot_program = blk_crypto_keyslot_program, + .keyslot_evict = blk_crypto_keyslot_evict, + .keyslot_find = blk_crypto_keyslot_find, + .crypto_mode_supported = blk_crypto_mode_supported, +}; + +static void blk_crypto_encrypt_endio(struct bio *enc_bio) +{ + struct bio *src_bio = enc_bio->bi_private; + int i; + + for (i = 0; i < enc_bio->bi_vcnt; i++) + mempool_free(enc_bio->bi_io_vec[i].bv_page, + blk_crypto_page_pool); + + src_bio->bi_status = enc_bio->bi_status; + + bio_put(enc_bio); + bio_endio(src_bio); +} + +static struct bio *blk_crypto_clone_bio(struct bio *bio_src) +{ + struct bvec_iter iter; + struct bio_vec bv; + struct bio *bio; + + bio = bio_alloc_bioset(GFP_NOIO, bio_segments(bio_src), NULL); + if (!bio) + return NULL; + bio->bi_disk = bio_src->bi_disk; + bio->bi_opf = bio_src->bi_opf; + bio->bi_ioprio = bio_src->bi_ioprio; + bio->bi_write_hint = bio_src->bi_write_hint; + bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; + bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; + + bio_for_each_segment(bv, bio_src, iter) + bio->bi_io_vec[bio->bi_vcnt++] = bv; + + if (bio_integrity(bio_src) && + bio_integrity_clone(bio, bio_src, GFP_NOIO) < 0) { + bio_put(bio); + return NULL; + } + + bio_clone_blkg_association(bio, bio_src); + blkcg_bio_issue_init(bio); + + return bio; +} + +/* Check that all I/O segments are data unit aligned */ +static int bio_crypt_check_alignment(struct bio *bio) +{ + int data_unit_size = 1 << bio->bi_crypt_context->data_unit_size_bits; + struct bvec_iter iter; + struct bio_vec bv; + + bio_for_each_segment(bv, bio, iter) { + if (!IS_ALIGNED(bv.bv_len | bv.bv_offset, data_unit_size)) + return -EIO; + } + return 0; +} + +static int blk_crypto_alloc_cipher_req(struct bio *src_bio, + struct skcipher_request **ciph_req_ptr, + struct crypto_wait *wait) +{ + int slot; + struct skcipher_request *ciph_req; + struct blk_crypto_keyslot *slotp; + + slot = bio_crypt_get_keyslot(src_bio); + slotp = &blk_crypto_keyslots[slot]; + ciph_req = skcipher_request_alloc(slotp->tfms[slotp->crypto_mode], + GFP_NOIO); + if (!ciph_req) { + src_bio->bi_status = BLK_STS_RESOURCE; + return -ENOMEM; + } + + skcipher_request_set_callback(ciph_req, + CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, wait); + *ciph_req_ptr = ciph_req; + return 0; +} + +static int blk_crypto_split_bio_if_needed(struct bio **bio_ptr) +{ + struct bio *bio = *bio_ptr; + unsigned int i = 0; + unsigned int num_sectors = 0; + struct bio_vec bv; + struct bvec_iter iter; + + bio_for_each_segment(bv, bio, iter) { + num_sectors += bv.bv_len >> SECTOR_SHIFT; + if (++i == BIO_MAX_PAGES) + break; + } + if (num_sectors < bio_sectors(bio)) { + struct bio *split_bio; + + split_bio = bio_split(bio, num_sectors, GFP_NOIO, NULL); + if (!split_bio) { + bio->bi_status = BLK_STS_RESOURCE; + return -ENOMEM; + } + bio_chain(split_bio, bio); + generic_make_request(bio); + *bio_ptr = split_bio; + } + return 0; +} + +/* + * The crypto API fallback's encryption routine. + * Allocate a bounce bio for encryption, encrypt the input bio using + * crypto API, and replace *bio_ptr with the bounce bio. May split input + * bio if it's too large. + */ +static int blk_crypto_encrypt_bio(struct bio **bio_ptr) +{ + struct bio *src_bio; + struct skcipher_request *ciph_req = NULL; + DECLARE_CRYPTO_WAIT(wait); + int err = 0; + u64 curr_dun; + union { + __le64 dun; + u8 bytes[16]; + } iv; + struct scatterlist src, dst; + struct bio *enc_bio; + struct bio_vec *enc_bvec; + int i, j; + int data_unit_size; + + /* Split the bio if it's too big for single page bvec */ + err = blk_crypto_split_bio_if_needed(bio_ptr); + if (err) + return err; + + src_bio = *bio_ptr; + data_unit_size = 1 << src_bio->bi_crypt_context->data_unit_size_bits; + + /* Allocate bounce bio for encryption */ + enc_bio = blk_crypto_clone_bio(src_bio); + if (!enc_bio) { + src_bio->bi_status = BLK_STS_RESOURCE; + return -ENOMEM; + } + + /* + * Use the crypto API fallback keyslot manager to get a crypto_skcipher + * for the algorithm and key specified for this bio. + */ + err = bio_crypt_ctx_acquire_keyslot(src_bio, blk_crypto_ksm); + if (err) { + src_bio->bi_status = BLK_STS_IOERR; + goto out_put_enc_bio; + } + + /* and then allocate an skcipher_request for it */ + err = blk_crypto_alloc_cipher_req(src_bio, &ciph_req, &wait); + if (err) + goto out_release_keyslot; + + curr_dun = bio_crypt_data_unit_num(src_bio); + sg_init_table(&src, 1); + sg_init_table(&dst, 1); + + skcipher_request_set_crypt(ciph_req, &src, &dst, + data_unit_size, iv.bytes); + + /* Encrypt each page in the bounce bio */ + for (i = 0, enc_bvec = enc_bio->bi_io_vec; i < enc_bio->bi_vcnt; + enc_bvec++, i++) { + struct page *plaintext_page = enc_bvec->bv_page; + struct page *ciphertext_page = + mempool_alloc(blk_crypto_page_pool, GFP_NOIO); + + enc_bvec->bv_page = ciphertext_page; + + if (!ciphertext_page) { + src_bio->bi_status = BLK_STS_RESOURCE; + err = -ENOMEM; + goto out_free_bounce_pages; + } + + sg_set_page(&src, plaintext_page, data_unit_size, + enc_bvec->bv_offset); + sg_set_page(&dst, ciphertext_page, data_unit_size, + enc_bvec->bv_offset); + + /* Encrypt each data unit in this page */ + for (j = 0; j < enc_bvec->bv_len; j += data_unit_size) { + memset(&iv, 0, sizeof(iv)); + iv.dun = cpu_to_le64(curr_dun); + + err = crypto_wait_req(crypto_skcipher_encrypt(ciph_req), + &wait); + if (err) { + i++; + src_bio->bi_status = BLK_STS_RESOURCE; + goto out_free_bounce_pages; + } + curr_dun++; + src.offset += data_unit_size; + dst.offset += data_unit_size; + } + } + + enc_bio->bi_private = src_bio; + enc_bio->bi_end_io = blk_crypto_encrypt_endio; + *bio_ptr = enc_bio; + + enc_bio = NULL; + err = 0; + goto out_free_ciph_req; + +out_free_bounce_pages: + while (i > 0) + mempool_free(enc_bio->bi_io_vec[--i].bv_page, + blk_crypto_page_pool); +out_free_ciph_req: + skcipher_request_free(ciph_req); +out_release_keyslot: + bio_crypt_ctx_release_keyslot(src_bio); +out_put_enc_bio: + if (enc_bio) + bio_put(enc_bio); + + return err; +} + +/* + * The crypto API fallback's main decryption routine. + * Decrypts input bio in place. + */ +static void blk_crypto_decrypt_bio(struct work_struct *w) +{ + struct work_mem *work_mem = + container_of(w, struct work_mem, crypto_work); + struct bio *bio = work_mem->bio; + struct skcipher_request *ciph_req = NULL; + DECLARE_CRYPTO_WAIT(wait); + struct bio_vec bv; + struct bvec_iter iter; + u64 curr_dun; + union { + __le64 dun; + u8 bytes[16]; + } iv; + struct scatterlist sg; + int data_unit_size = 1 << bio->bi_crypt_context->data_unit_size_bits; + int i; + int err; + + /* + * Use the crypto API fallback keyslot manager to get a crypto_skcipher + * for the algorithm and key specified for this bio. + */ + if (bio_crypt_ctx_acquire_keyslot(bio, blk_crypto_ksm)) { + bio->bi_status = BLK_STS_RESOURCE; + goto out_no_keyslot; + } + + /* and then allocate an skcipher_request for it */ + err = blk_crypto_alloc_cipher_req(bio, &ciph_req, &wait); + if (err) + goto out; + + curr_dun = bio_crypt_sw_data_unit_num(bio); + sg_init_table(&sg, 1); + skcipher_request_set_crypt(ciph_req, &sg, &sg, data_unit_size, + iv.bytes); + + /* Decrypt each segment in the bio */ + __bio_for_each_segment(bv, bio, iter, + bio->bi_crypt_context->crypt_iter) { + struct page *page = bv.bv_page; + + sg_set_page(&sg, page, data_unit_size, bv.bv_offset); + + /* Decrypt each data unit in the segment */ + for (i = 0; i < bv.bv_len; i += data_unit_size) { + memset(&iv, 0, sizeof(iv)); + iv.dun = cpu_to_le64(curr_dun); + if (crypto_wait_req(crypto_skcipher_decrypt(ciph_req), + &wait)) { + bio->bi_status = BLK_STS_IOERR; + goto out; + } + curr_dun++; + sg.offset += data_unit_size; + } + } + +out: + skcipher_request_free(ciph_req); + bio_crypt_ctx_release_keyslot(bio); +out_no_keyslot: + kmem_cache_free(blk_crypto_work_mem_cache, work_mem); + bio_endio(bio); +} + +/* Queue bio for decryption */ +static void blk_crypto_queue_decrypt_bio(struct bio *bio) +{ + struct work_mem *work_mem = + kmem_cache_zalloc(blk_crypto_work_mem_cache, GFP_ATOMIC); + + if (!work_mem) { + bio->bi_status = BLK_STS_RESOURCE; + bio_endio(bio); + return; + } + + INIT_WORK(&work_mem->crypto_work, blk_crypto_decrypt_bio); + work_mem->bio = bio; + queue_work(blk_crypto_wq, &work_mem->crypto_work); +} + +/** + * blk_crypto_submit_bio - handle submitting bio for inline encryption + * + * @bio_ptr: pointer to original bio pointer + * + * If the bio doesn't have inline encryption enabled or the submitter already + * specified a keyslot for the target device, do nothing. Else, a raw key must + * have been provided, so acquire a device keyslot for it if supported. Else, + * use the crypto API fallback. + * + * When the crypto API fallback is used for encryption, blk-crypto may choose to + * split the bio into 2 - the first one that will continue to be processed and + * the second one that will be resubmitted via generic_make_request. + * A bounce bio will be allocated to encrypt the contents of the aforementioned + * "first one", and *bio_ptr will be updated to this bounce bio. + * + * Return: 0 if bio submission should continue; nonzero if bio_endio() was + * already called so bio submission should abort. + */ +int blk_crypto_submit_bio(struct bio **bio_ptr) +{ + struct bio *bio = *bio_ptr; + struct request_queue *q; + int err; + struct bio_crypt_ctx *crypt_ctx; + + if (!bio_has_crypt_ctx(bio) || !bio_has_data(bio)) + return 0; + + /* + * When a read bio is marked for sw decryption, its bi_iter is saved + * so that when we decrypt the bio later, we know what part of it was + * marked for sw decryption (when the bio is passed down after + * blk_crypto_submit bio, it may be split or advanced so we cannot rely + * on the bi_iter while decrypting in blk_crypto_endio) + */ + if (bio_crypt_swhandled(bio)) + return 0; + + err = bio_crypt_check_alignment(bio); + if (err) { + bio->bi_status = BLK_STS_IOERR; + goto out; + } + + crypt_ctx = bio->bi_crypt_context; + q = bio->bi_disk->queue; + + if (bio_crypt_has_keyslot(bio)) { + /* Key already programmed into device? */ + if (q->ksm == crypt_ctx->processing_ksm) + return 0; + + /* Nope, release the existing keyslot. */ + bio_crypt_ctx_release_keyslot(bio); + } + + /* Get device keyslot if supported */ + if (q->ksm) { + err = bio_crypt_ctx_acquire_keyslot(bio, q->ksm); + if (!err) + return 0; + + pr_warn_once("Failed to acquire keyslot for %s (err=%d). Falling back to crypto API.\n", + bio->bi_disk->disk_name, err); + } + + /* Fallback to crypto API */ + if (!READ_ONCE(tfms_inited[bio->bi_crypt_context->crypto_mode])) { + err = -EIO; + bio->bi_status = BLK_STS_IOERR; + goto out; + } + + if (bio_data_dir(bio) == WRITE) { + /* Encrypt the data now */ + err = blk_crypto_encrypt_bio(bio_ptr); + if (err) + goto out; + } else { + /* Mark bio as swhandled */ + bio->bi_crypt_context->processing_ksm = blk_crypto_ksm; + bio->bi_crypt_context->crypt_iter = bio->bi_iter; + bio->bi_crypt_context->sw_data_unit_num = + bio->bi_crypt_context->data_unit_num; + } + return 0; +out: + bio_endio(*bio_ptr); + return err; +} + +/** + * blk_crypto_endio - clean up bio w.r.t inline encryption during bio_endio + * + * @bio - the bio to clean up + * + * If blk_crypto_submit_bio decided to fallback to crypto API for this + * bio, we queue the bio for decryption into a workqueue and return false, + * and call bio_endio(bio) at a later time (after the bio has been decrypted). + * + * If the bio is not to be decrypted by the crypto API, this function releases + * the reference to the keyslot that blk_crypto_submit_bio got. + * + * Return: true if bio_endio should continue; false otherwise (bio_endio will + * be called again when bio has been decrypted). + */ +bool blk_crypto_endio(struct bio *bio) +{ + if (!bio_has_crypt_ctx(bio)) + return true; + + if (bio_crypt_swhandled(bio)) { + /* + * The only bios that are swhandled when they reach here + * are those with bio_data_dir(bio) == READ, since WRITE + * bios that are encrypted by the crypto API fallback are + * handled by blk_crypto_encrypt_endio. + */ + + /* If there was an IO error, don't decrypt. */ + if (bio->bi_status) + return true; + + blk_crypto_queue_decrypt_bio(bio); + return false; + } + + if (bio_crypt_has_keyslot(bio)) + bio_crypt_ctx_release_keyslot(bio); + + return true; +} + +/** + * blk_crypto_start_using_mode() - Allocate skciphers for a + * mode_num for all keyslots + * @mode_num - the blk_crypto_mode we want to allocate ciphers for. + * + * Upper layers (filesystems) should call this function to ensure that a + * the crypto API fallback has transforms for this algorithm, if they become + * necessary. + * + * Return: 0 on success and -err on error. + */ +int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, + unsigned int data_unit_size, + struct request_queue *q) +{ + struct blk_crypto_keyslot *slotp; + int err = 0; + int i; + + /* + * Fast path + * Ensure that updates to blk_crypto_keyslots[i].tfms[mode_num] + * for each i are visible before we try to access them. + */ + if (likely(smp_load_acquire(&tfms_inited[mode_num]))) + return 0; + + /* + * If the keyslot manager of the request queue supports this + * crypto mode, then we don't need to allocate this mode. + */ + if (keyslot_manager_crypto_mode_supported(q->ksm, mode_num, + data_unit_size)) { + return 0; + } + + mutex_lock(&tfms_lock[mode_num]); + if (likely(tfms_inited[mode_num])) + goto out; + + for (i = 0; i < blk_crypto_num_keyslots; i++) { + slotp = &blk_crypto_keyslots[i]; + slotp->tfms[mode_num] = crypto_alloc_skcipher( + blk_crypto_modes[mode_num].cipher_str, + 0, 0); + if (IS_ERR(slotp->tfms[mode_num])) { + err = PTR_ERR(slotp->tfms[mode_num]); + slotp->tfms[mode_num] = NULL; + goto out_free_tfms; + } + + crypto_skcipher_set_flags(slotp->tfms[mode_num], + CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); + } + + /* + * Ensure that updates to blk_crypto_keyslots[i].tfms[mode_num] + * for each i are visible before we set tfms_inited[mode_num]. + */ + smp_store_release(&tfms_inited[mode_num], true); + goto out; + +out_free_tfms: + for (i = 0; i < blk_crypto_num_keyslots; i++) { + slotp = &blk_crypto_keyslots[i]; + crypto_free_skcipher(slotp->tfms[mode_num]); + slotp->tfms[mode_num] = NULL; + } +out: + mutex_unlock(&tfms_lock[mode_num]); + return err; +} +EXPORT_SYMBOL(blk_crypto_start_using_mode); + +/** + * blk_crypto_evict_key() - Evict a key from any inline encryption hardware + * it may have been programmed into + * @q - The request queue who's keyslot manager this key might have been + * programmed into + * @key - The key to evict + * @mode - The blk_crypto_mode_num used with this key + * @data_unit_size - The data unit size used with this key + * + * Upper layers (filesystems) should call this function to ensure that a key + * is evicted from hardware that it might have been programmed into. This + * will call keyslot_manager_evict_key on the queue's keyslot manager, if one + * exists, and supports the crypto algorithm with the specified data unit size. + * Otherwise, it will evict the key from the blk_crypto_ksm. + * + * Return: 0 on success, -err on error. + */ +int blk_crypto_evict_key(struct request_queue *q, const u8 *key, + enum blk_crypto_mode_num mode, + unsigned int data_unit_size) +{ + struct keyslot_manager *ksm = blk_crypto_ksm; + + if (q && q->ksm && keyslot_manager_crypto_mode_supported(q->ksm, mode, + data_unit_size)) { + ksm = q->ksm; + } + + return keyslot_manager_evict_key(ksm, key, mode, data_unit_size); +} +EXPORT_SYMBOL(blk_crypto_evict_key); + +int __init blk_crypto_init(void) +{ + int i; + int err = -ENOMEM; + + prandom_bytes(blank_key, BLK_CRYPTO_MAX_KEY_SIZE); + + blk_crypto_ksm = keyslot_manager_create(blk_crypto_num_keyslots, + &blk_crypto_ksm_ll_ops, + NULL); + if (!blk_crypto_ksm) + goto out; + + blk_crypto_wq = alloc_workqueue("blk_crypto_wq", + WQ_UNBOUND | WQ_HIGHPRI | + WQ_MEM_RECLAIM, + num_online_cpus()); + if (!blk_crypto_wq) + goto out_free_ksm; + + blk_crypto_keyslots = kcalloc(blk_crypto_num_keyslots, + sizeof(*blk_crypto_keyslots), + GFP_KERNEL); + if (!blk_crypto_keyslots) + goto out_free_workqueue; + + for (i = 0; i < blk_crypto_num_keyslots; i++) { + blk_crypto_keyslots[i].crypto_mode = + BLK_ENCRYPTION_MODE_INVALID; + } + + for (i = 0; i < ARRAY_SIZE(blk_crypto_modes); i++) + mutex_init(&tfms_lock[i]); + + blk_crypto_page_pool = + mempool_create_page_pool(num_prealloc_bounce_pg, 0); + if (!blk_crypto_page_pool) + goto out_free_keyslots; + + blk_crypto_work_mem_cache = KMEM_CACHE(work_mem, SLAB_RECLAIM_ACCOUNT); + if (!blk_crypto_work_mem_cache) + goto out_free_page_pool; + + return 0; + +out_free_page_pool: + mempool_destroy(blk_crypto_page_pool); + blk_crypto_page_pool = NULL; +out_free_keyslots: + kzfree(blk_crypto_keyslots); + blk_crypto_keyslots = NULL; +out_free_workqueue: + destroy_workqueue(blk_crypto_wq); + blk_crypto_wq = NULL; +out_free_ksm: + keyslot_manager_destroy(blk_crypto_ksm); + blk_crypto_ksm = NULL; +out: + pr_warn("No memory for blk-crypto crypto API fallback."); + return err; +} diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 2a3db80c1dce7f97c65229510d078e3553615fc4..a7ed434eae0387b92d41009b0cc52f3522ed556c 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -2110,10 +2110,10 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf, goto einval; } - spin_lock_irq(&iocg->ioc->lock); + spin_lock(&iocg->ioc->lock); iocg->cfg_weight = v; weight_updated(iocg); - spin_unlock_irq(&iocg->ioc->lock); + spin_unlock(&iocg->ioc->lock); blkg_conf_finish(&ctx); return nbytes; diff --git a/block/blk-merge.c b/block/blk-merge.c index 48e6725b32eeacc749664d19fe151df6e2b7818c..c97c02a20c6a4500bba38d3ee45151b7bdd535ec 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -557,6 +557,9 @@ static inline int ll_new_hw_segment(struct request *req, struct bio *bio, if (blk_integrity_merge_bio(req->q, req, bio) == false) goto no_merge; + if (WARN_ON_ONCE(!bio_crypt_ctx_compatible(bio, req->bio))) + goto no_merge; + /* * This will form the start of a new hw segment. Bump both * counters. @@ -711,8 +714,14 @@ static enum elv_merge blk_try_req_merge(struct request *req, { if (blk_discard_mergable(req)) return ELEVATOR_DISCARD_MERGE; - else if (blk_rq_pos(req) + blk_rq_sectors(req) == blk_rq_pos(next)) + else if (blk_rq_pos(req) + blk_rq_sectors(req) == blk_rq_pos(next)) { + if (!bio_crypt_ctx_back_mergeable(req->bio, + blk_rq_sectors(req), + next->bio)) { + return ELEVATOR_NO_MERGE; + } return ELEVATOR_BACK_MERGE; + } return ELEVATOR_NO_MERGE; } @@ -748,6 +757,9 @@ static struct request *attempt_merge(struct request_queue *q, if (req->ioprio != next->ioprio) return NULL; + if (!bio_crypt_ctx_compatible(req->bio, next->bio)) + return NULL; + /* * If we are allowed to merge, then append bio list * from next to rq and release next. merge_requests_fn @@ -880,16 +892,31 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) if (rq->ioprio != bio_prio(bio)) return false; + /* Only merge if the crypt contexts are compatible */ + if (!bio_crypt_ctx_compatible(bio, rq->bio)) + return false; + return true; } enum elv_merge blk_try_merge(struct request *rq, struct bio *bio) { - if (blk_discard_mergable(rq)) + if (blk_discard_mergable(rq)) { return ELEVATOR_DISCARD_MERGE; - else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector) + } else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == + bio->bi_iter.bi_sector) { + if (!bio_crypt_ctx_back_mergeable(rq->bio, + blk_rq_sectors(rq), bio)) { + return ELEVATOR_NO_MERGE; + } return ELEVATOR_BACK_MERGE; - else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector) + } else if (blk_rq_pos(rq) - bio_sectors(bio) == + bio->bi_iter.bi_sector) { + if (!bio_crypt_ctx_back_mergeable(bio, + bio_sectors(bio), rq->bio)) { + return ELEVATOR_NO_MERGE; + } return ELEVATOR_FRONT_MERGE; + } return ELEVATOR_NO_MERGE; } diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h index e8cb68f6958a286ff3aedc585615ee0d46bf6c46..2bc43e94f4c407582087e328d892f0c5d1e4da86 100644 --- a/block/blk-rq-qos.h +++ b/block/blk-rq-qos.h @@ -108,16 +108,13 @@ static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos) static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos) { - struct rq_qos *cur, *prev = NULL; - for (cur = q->rq_qos; cur; cur = cur->next) { - if (cur == rqos) { - if (prev) - prev->next = rqos->next; - else - q->rq_qos = cur; + struct rq_qos **cur; + + for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) { + if (*cur == rqos) { + *cur = rqos->next; break; } - prev = cur; } blk_mq_debugfs_unregister_rqos(rqos); diff --git a/block/bounce.c b/block/bounce.c index f8ed677a1bf7ed3aed23f3edbd68dc2d61cf8e7c..6f9a2359b22a508a4da3ceb9d2927a773394c844 100644 --- a/block/bounce.c +++ b/block/bounce.c @@ -267,14 +267,15 @@ static struct bio *bounce_clone_bio(struct bio *bio_src, gfp_t gfp_mask, break; } - if (bio_integrity(bio_src)) { - int ret; + if (bio_crypt_clone(bio, bio_src, gfp_mask) < 0) { + bio_put(bio); + return NULL; + } - ret = bio_integrity_clone(bio, bio_src, gfp_mask); - if (ret < 0) { - bio_put(bio); - return NULL; - } + if (bio_integrity(bio_src) && + bio_integrity_clone(bio, bio_src, gfp_mask) < 0) { + bio_put(bio); + return NULL; } bio_clone_blkg_association(bio, bio_src); diff --git a/block/elevator.c b/block/elevator.c index 5437059c92615ea9c474342d31ad4348e788bf19..076ba7308e65c34a8e4abd1df484d7388b8a4494 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -616,7 +616,8 @@ int elevator_switch_mq(struct request_queue *q, static inline bool elv_support_iosched(struct request_queue *q) { - if (q->tag_set && (q->tag_set->flags & BLK_MQ_F_NO_SCHED)) + if (!q->mq_ops || + (q->tag_set && (q->tag_set->flags & BLK_MQ_F_NO_SCHED))) return false; return true; } diff --git a/block/keyslot-manager.c b/block/keyslot-manager.c new file mode 100644 index 0000000000000000000000000000000000000000..020931fc9f7d2205723869acf732ba4998030c30 --- /dev/null +++ b/block/keyslot-manager.c @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * keyslot-manager.c + * + * Copyright 2019 Google LLC + */ + +/** + * DOC: The Keyslot Manager + * + * Many devices with inline encryption support have a limited number of "slots" + * into which encryption contexts may be programmed, and requests can be tagged + * with a slot number to specify the key to use for en/decryption. + * + * As the number of slots are limited, and programming keys is expensive on + * many inline encryption hardware, we don't want to program the same key into + * multiple slots - if multiple requests are using the same key, we want to + * program just one slot with that key and use that slot for all requests. + * + * The keyslot manager manages these keyslots appropriately, and also acts as + * an abstraction between the inline encryption hardware and the upper layers. + * + * Lower layer devices will set up a keyslot manager in their request queue + * and tell it how to perform device specific operations like programming/ + * evicting keys from keyslots. + * + * Upper layers will call keyslot_manager_get_slot_for_key() to program a + * key into some slot in the inline encryption hardware. + */ +#include +#include +#include +#include +#include + +struct keyslot { + atomic_t slot_refs; + struct list_head idle_slot_node; +}; + +struct keyslot_manager { + unsigned int num_slots; + atomic_t num_idle_slots; + struct keyslot_mgmt_ll_ops ksm_ll_ops; + void *ll_priv_data; + + /* Protects programming and evicting keys from the device */ + struct rw_semaphore lock; + + /* List of idle slots, with least recently used slot at front */ + wait_queue_head_t idle_slots_wait_queue; + struct list_head idle_slots; + spinlock_t idle_slots_lock; + + /* Per-keyslot data */ + struct keyslot slots[]; +}; + +/** + * keyslot_manager_create() - Create a keyslot manager + * @num_slots: The number of key slots to manage. + * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot + * manager will use to perform operations like programming and + * evicting keys. + * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops. + * + * Allocate memory for and initialize a keyslot manager. Called by e.g. + * storage drivers to set up a keyslot manager in their request_queue. + * + * Context: May sleep + * Return: Pointer to constructed keyslot manager or NULL on error. + */ +struct keyslot_manager *keyslot_manager_create(unsigned int num_slots, + const struct keyslot_mgmt_ll_ops *ksm_ll_ops, + void *ll_priv_data) +{ + struct keyslot_manager *ksm; + int slot; + + if (num_slots == 0) + return NULL; + + /* Check that all ops are specified */ + if (ksm_ll_ops->keyslot_program == NULL || + ksm_ll_ops->keyslot_evict == NULL || + ksm_ll_ops->crypto_mode_supported == NULL || + ksm_ll_ops->keyslot_find == NULL) + return NULL; + + ksm = kvzalloc(struct_size(ksm, slots, num_slots), GFP_KERNEL); + if (!ksm) + return NULL; + + ksm->num_slots = num_slots; + atomic_set(&ksm->num_idle_slots, num_slots); + ksm->ksm_ll_ops = *ksm_ll_ops; + ksm->ll_priv_data = ll_priv_data; + + init_rwsem(&ksm->lock); + + init_waitqueue_head(&ksm->idle_slots_wait_queue); + INIT_LIST_HEAD(&ksm->idle_slots); + + for (slot = 0; slot < num_slots; slot++) { + list_add_tail(&ksm->slots[slot].idle_slot_node, + &ksm->idle_slots); + } + + spin_lock_init(&ksm->idle_slots_lock); + + return ksm; +} +EXPORT_SYMBOL(keyslot_manager_create); + +static void remove_slot_from_lru_list(struct keyslot_manager *ksm, int slot) +{ + unsigned long flags; + + spin_lock_irqsave(&ksm->idle_slots_lock, flags); + list_del(&ksm->slots[slot].idle_slot_node); + spin_unlock_irqrestore(&ksm->idle_slots_lock, flags); + + atomic_dec(&ksm->num_idle_slots); +} + +static int find_and_grab_keyslot(struct keyslot_manager *ksm, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + int slot; + + slot = ksm->ksm_ll_ops.keyslot_find(ksm->ll_priv_data, key, + crypto_mode, data_unit_size); + if (slot < 0) + return slot; + if (WARN_ON(slot >= ksm->num_slots)) + return -EINVAL; + if (atomic_inc_return(&ksm->slots[slot].slot_refs) == 1) { + /* Took first reference to this slot; remove it from LRU list */ + remove_slot_from_lru_list(ksm, slot); + } + return slot; +} + +/** + * keyslot_manager_get_slot_for_key() - Program a key into a keyslot. + * @ksm: The keyslot manager to program the key into. + * @key: Pointer to the bytes of the key to program. Must be the correct length + * for the chosen @crypto_mode; see blk_crypto_modes in blk-crypto.c. + * @crypto_mode: Identifier for the encryption algorithm to use. + * @data_unit_size: The data unit size to use for en/decryption. + * + * Get a keyslot that's been programmed with the specified key, crypto_mode, and + * data_unit_size. If one already exists, return it with incremented refcount. + * Otherwise, wait for a keyslot to become idle and program it. + * + * Context: Process context. Takes and releases ksm->lock. + * Return: The keyslot on success, else a -errno value. + */ +int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm, + const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + int slot; + int err; + struct keyslot *idle_slot; + + down_read(&ksm->lock); + slot = find_and_grab_keyslot(ksm, key, crypto_mode, data_unit_size); + up_read(&ksm->lock); + if (slot != -ENOKEY) + return slot; + + for (;;) { + down_write(&ksm->lock); + slot = find_and_grab_keyslot(ksm, key, crypto_mode, + data_unit_size); + if (slot != -ENOKEY) { + up_write(&ksm->lock); + return slot; + } + + /* + * If we're here, that means there wasn't a slot that was + * already programmed with the key. So try to program it. + */ + if (atomic_read(&ksm->num_idle_slots) > 0) + break; + + up_write(&ksm->lock); + wait_event(ksm->idle_slots_wait_queue, + (atomic_read(&ksm->num_idle_slots) > 0)); + } + + idle_slot = list_first_entry(&ksm->idle_slots, struct keyslot, + idle_slot_node); + slot = idle_slot - ksm->slots; + + err = ksm->ksm_ll_ops.keyslot_program(ksm->ll_priv_data, key, + crypto_mode, + data_unit_size, + slot); + + if (err) { + wake_up(&ksm->idle_slots_wait_queue); + up_write(&ksm->lock); + return err; + } + + atomic_set(&ksm->slots[slot].slot_refs, 1); + remove_slot_from_lru_list(ksm, slot); + + up_write(&ksm->lock); + return slot; + +} +EXPORT_SYMBOL(keyslot_manager_get_slot_for_key); + +/** + * keyslot_manager_get_slot() - Increment the refcount on the specified slot. + * @ksm - The keyslot manager that we want to modify. + * @slot - The slot to increment the refcount of. + * + * This function assumes that there is already an active reference to that slot + * and simply increments the refcount. This is useful when cloning a bio that + * already has a reference to a keyslot, and we want the cloned bio to also have + * its own reference. + * + * Context: Any context. + */ +void keyslot_manager_get_slot(struct keyslot_manager *ksm, unsigned int slot) +{ + if (WARN_ON(slot >= ksm->num_slots)) + return; + + WARN_ON(atomic_inc_return(&ksm->slots[slot].slot_refs) < 2); +} +EXPORT_SYMBOL(keyslot_manager_get_slot); + +/** + * keyslot_manager_put_slot() - Release a reference to a slot + * @ksm: The keyslot manager to release the reference from. + * @slot: The slot to release the reference from. + * + * Context: Any context. + */ +void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot) +{ + unsigned long flags; + + if (WARN_ON(slot >= ksm->num_slots)) + return; + + if (atomic_dec_and_lock_irqsave(&ksm->slots[slot].slot_refs, + &ksm->idle_slots_lock, flags)) { + list_add_tail(&ksm->slots[slot].idle_slot_node, + &ksm->idle_slots); + spin_unlock_irqrestore(&ksm->idle_slots_lock, flags); + atomic_inc(&ksm->num_idle_slots); + wake_up(&ksm->idle_slots_wait_queue); + } +} +EXPORT_SYMBOL(keyslot_manager_put_slot); + +/** + * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data + * unit size combination is supported + * by a ksm. + * @ksm - The keyslot manager to check + * @crypto_mode - The crypto mode to check for. + * @data_unit_size - The data_unit_size for the mode. + * + * Calls and returns the result of the crypto_mode_supported function specified + * by the ksm. + * + * Context: Process context. + * Return: Whether or not this ksm supports the specified crypto_mode/ + * data_unit_size combo. + */ +bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + if (!ksm) + return false; + return ksm->ksm_ll_ops.crypto_mode_supported(ksm->ll_priv_data, + crypto_mode, + data_unit_size); +} +EXPORT_SYMBOL(keyslot_manager_crypto_mode_supported); + +bool keyslot_manager_rq_crypto_mode_supported(struct request_queue *q, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + return keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode, + data_unit_size); +} +EXPORT_SYMBOL(keyslot_manager_rq_crypto_mode_supported); + +/** + * keyslot_manager_evict_key() - Evict a key from the lower layer device. + * @ksm - The keyslot manager to evict from + * @key - The key to evict + * @crypto_mode - The crypto algorithm the key was programmed with. + * @data_unit_size - The data_unit_size the key was programmed with. + * + * Finds the slot that the specified key, crypto_mode, data_unit_size combo + * was programmed into, and evicts that slot from the lower layer device if + * the refcount on the slot is 0. Returns -EBUSY if the refcount is not 0, and + * -errno on error. + * + * Context: Process context. Takes and releases ksm->lock. + */ +int keyslot_manager_evict_key(struct keyslot_manager *ksm, + const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + int slot; + int err = 0; + + down_write(&ksm->lock); + slot = ksm->ksm_ll_ops.keyslot_find(ksm->ll_priv_data, key, + crypto_mode, + data_unit_size); + + if (slot < 0) { + up_write(&ksm->lock); + return slot; + } + + if (atomic_read(&ksm->slots[slot].slot_refs) == 0) { + err = ksm->ksm_ll_ops.keyslot_evict(ksm->ll_priv_data, key, + crypto_mode, + data_unit_size, + slot); + } else { + err = -EBUSY; + } + + up_write(&ksm->lock); + return err; +} +EXPORT_SYMBOL(keyslot_manager_evict_key); + +void keyslot_manager_destroy(struct keyslot_manager *ksm) +{ + kvfree(ksm); +} +EXPORT_SYMBOL(keyslot_manager_destroy); diff --git a/build.config.allmodconfig b/build.config.allmodconfig index 854a8f8aa3f2f0a0de16131b048b41d13601b6e2..b39bc1b877c7ed7db95cb085e47e0da4386157dc 100644 --- a/build.config.allmodconfig +++ b/build.config.allmodconfig @@ -9,7 +9,9 @@ function update_config() { -d TEST_KMOD \ -d XFS_FS \ -d CPU_BIG_ENDIAN \ - -d KVM_INTEL + -d STM \ + -d TEST_MEMCAT_P \ + (cd ${OUT_DIR} && \ make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig) } diff --git a/build.config.common b/build.config.common index a879f6282c0f3246a0a2632547d78d0416a75a12..d9895bb9ad641a1e43a061106c6a6d0dd1cbac50 100644 --- a/build.config.common +++ b/build.config.common @@ -2,6 +2,7 @@ BRANCH=android-mainline KERNEL_DIR=common CC=clang +LD=ld.lld CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r365631c/bin BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 3b2525908dd8cfaed9074d7926d2036102e77f34..a1a858ad4d18d57117eaf3e2a65ca26985754f0a 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -905,8 +905,8 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr) pcc_data[pcc_ss_id]->refcount--; if (!pcc_data[pcc_ss_id]->refcount) { pcc_mbox_free_channel(pcc_data[pcc_ss_id]->pcc_channel); - pcc_data[pcc_ss_id]->pcc_channel_acquired = 0; kfree(pcc_data[pcc_ss_id]); + pcc_data[pcc_ss_id] = NULL; } } } diff --git a/drivers/acpi/hmat/hmat.c b/drivers/acpi/hmat/hmat.c index 8f9a28a870b0c5a4315c683abe7a67b0da28a664..8b0de8a3c64709652ae327b8d19b9d0d141d856a 100644 --- a/drivers/acpi/hmat/hmat.c +++ b/drivers/acpi/hmat/hmat.c @@ -403,7 +403,7 @@ static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *heade pr_info("HMAT: Memory Flags:%04x Processor Domain:%d Memory Domain:%d\n", p->flags, p->processor_PD, p->memory_PD); - if (p->flags & ACPI_HMAT_MEMORY_PD_VALID) { + if (p->flags & ACPI_HMAT_MEMORY_PD_VALID && hmat_revision == 1) { target = find_mem_target(p->memory_PD); if (!target) { pr_debug("HMAT: Memory Domain missing from SRAT\n"); diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 1413324982f0d7628068711e61e598093b88d320..14e68f202f8109dfce44d19eee7274d68d1552bc 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -1322,7 +1322,7 @@ static ssize_t scrub_show(struct device *dev, nfit_device_lock(dev); nd_desc = dev_get_drvdata(dev); if (!nd_desc) { - device_unlock(dev); + nfit_device_unlock(dev); return rc; } acpi_desc = to_acpi_desc(nd_desc); diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 08da9c29f1e9a8fe722e5bfc7895357b5ec3277e..62114a03a51aa134dbf5254f105392c60c27a550 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -290,14 +290,13 @@ static int acpi_processor_notifier(struct notifier_block *nb, unsigned long event, void *data) { struct cpufreq_policy *policy = data; - int cpu = policy->cpu; if (event == CPUFREQ_CREATE_POLICY) { - acpi_thermal_cpufreq_init(cpu); - acpi_processor_ppc_init(cpu); + acpi_thermal_cpufreq_init(policy); + acpi_processor_ppc_init(policy); } else if (event == CPUFREQ_REMOVE_POLICY) { - acpi_processor_ppc_exit(cpu); - acpi_thermal_cpufreq_exit(cpu); + acpi_processor_ppc_exit(policy); + acpi_thermal_cpufreq_exit(policy); } return 0; diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 2261713d1aec08ffe2f006ff8fd69c165b32a6de..5909e8fa4013f2c6c831b1a28d9d69ca4cec98fb 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -81,10 +81,10 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) pr->performance_platform_limit = (int)ppc; if (ppc >= pr->performance->state_count || - unlikely(!dev_pm_qos_request_active(&pr->perflib_req))) + unlikely(!freq_qos_request_active(&pr->perflib_req))) return 0; - ret = dev_pm_qos_update_request(&pr->perflib_req, + ret = freq_qos_update_request(&pr->perflib_req, pr->performance->states[ppc].core_frequency * 1000); if (ret < 0) { pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n", @@ -157,26 +157,36 @@ void acpi_processor_ignore_ppc_init(void) ignore_ppc = 0; } -void acpi_processor_ppc_init(int cpu) +void acpi_processor_ppc_init(struct cpufreq_policy *policy) { - struct acpi_processor *pr = per_cpu(processors, cpu); - int ret; + unsigned int cpu; - ret = dev_pm_qos_add_request(get_cpu_device(cpu), - &pr->perflib_req, DEV_PM_QOS_MAX_FREQUENCY, - INT_MAX); - if (ret < 0) { - pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, - ret); - return; + for_each_cpu(cpu, policy->related_cpus) { + struct acpi_processor *pr = per_cpu(processors, cpu); + int ret; + + if (!pr) + continue; + + ret = freq_qos_add_request(&policy->constraints, + &pr->perflib_req, + FREQ_QOS_MAX, INT_MAX); + if (ret < 0) + pr_err("Failed to add freq constraint for CPU%d (%d)\n", + cpu, ret); } } -void acpi_processor_ppc_exit(int cpu) +void acpi_processor_ppc_exit(struct cpufreq_policy *policy) { - struct acpi_processor *pr = per_cpu(processors, cpu); + unsigned int cpu; - dev_pm_qos_remove_request(&pr->perflib_req); + for_each_cpu(cpu, policy->related_cpus) { + struct acpi_processor *pr = per_cpu(processors, cpu); + + if (pr) + freq_qos_remove_request(&pr->perflib_req); + } } static int acpi_processor_get_performance_control(struct acpi_processor *pr) diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index ec2638f1df4faea14e10a0682887bdce2d3e91e1..41feb88ee92d69380af6e4d30c92199e3e4dd4d1 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -105,7 +105,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) pr = per_cpu(processors, i); - if (unlikely(!dev_pm_qos_request_active(&pr->thermal_req))) + if (unlikely(!freq_qos_request_active(&pr->thermal_req))) continue; policy = cpufreq_cpu_get(i); @@ -116,7 +116,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) cpufreq_cpu_put(policy); - ret = dev_pm_qos_update_request(&pr->thermal_req, max_freq); + ret = freq_qos_update_request(&pr->thermal_req, max_freq); if (ret < 0) { pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n", pr->id, ret); @@ -125,26 +125,36 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) return 0; } -void acpi_thermal_cpufreq_init(int cpu) +void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy) { - struct acpi_processor *pr = per_cpu(processors, cpu); - int ret; - - ret = dev_pm_qos_add_request(get_cpu_device(cpu), - &pr->thermal_req, DEV_PM_QOS_MAX_FREQUENCY, - INT_MAX); - if (ret < 0) { - pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, - ret); - return; + unsigned int cpu; + + for_each_cpu(cpu, policy->related_cpus) { + struct acpi_processor *pr = per_cpu(processors, cpu); + int ret; + + if (!pr) + continue; + + ret = freq_qos_add_request(&policy->constraints, + &pr->thermal_req, + FREQ_QOS_MAX, INT_MAX); + if (ret < 0) + pr_err("Failed to add freq constraint for CPU%d (%d)\n", + cpu, ret); } } -void acpi_thermal_cpufreq_exit(int cpu) +void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy) { - struct acpi_processor *pr = per_cpu(processors, cpu); + unsigned int cpu; + + for_each_cpu(cpu, policy->related_cpus) { + struct acpi_processor *pr = per_cpu(processors, policy->cpu); - dev_pm_qos_remove_request(&pr->thermal_req); + if (pr) + freq_qos_remove_request(&pr->thermal_req); + } } #else /* ! CONFIG_CPU_FREQ */ static int cpufreq_get_max_state(unsigned int cpu) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 9fa77d72ef27f52369a23f9ed99788705661bc3a..2af937a8b1c5c8b5b621f6e75f7206feab9fe996 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -361,19 +361,6 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "80E3"), }, }, - /* - * https://bugzilla.kernel.org/show_bug.cgi?id=196907 - * Some Dell XPS13 9360 cannot do suspend-to-idle using the Low Power - * S0 Idle firmware interface. - */ - { - .callback = init_default_s3, - .ident = "Dell XPS13 9360", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"), - }, - }, /* * ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using * the Low Power S0 Idle firmware interface (see diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index f39f075abff9f71bac1f688db5483017957ad88c..fe1523664816a49712c88b4afcdc9ee65011b955 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -409,9 +409,11 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent) */ rstc = of_reset_control_array_get_optional_shared(dev->dev.of_node); if (IS_ERR(rstc)) { - if (PTR_ERR(rstc) != -EPROBE_DEFER) - dev_err(&dev->dev, "Can't get amba reset!\n"); - return PTR_ERR(rstc); + ret = PTR_ERR(rstc); + if (ret != -EPROBE_DEFER) + dev_err(&dev->dev, "can't get reset: %d\n", + ret); + goto err_reset; } reset_control_deassert(rstc); reset_control_put(rstc); @@ -472,6 +474,12 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent) release_resource(&dev->res); err_out: return ret; + + err_reset: + amba_put_disable_pclk(dev); + iounmap(tmp); + dev_pm_domain_detach(&dev->dev, true); + goto err_release; } /* diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 4cd82572785d158d40aa18b8a30d9de2ab9d1da0..bc431dbf94f5587b57d955a93331bc5bd78292ed 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -98,10 +98,6 @@ DEFINE_SHOW_ATTRIBUTE(proc); #define SZ_1K 0x400 #endif -#ifndef SZ_4M -#define SZ_4M 0x400000 -#endif - #define FORBIDDEN_MMAP_FLAGS (VM_WRITE) enum { @@ -2915,19 +2911,50 @@ static bool binder_proc_transaction(struct binder_transaction *t, struct binder_priority node_prio; bool oneway = !!(t->flags & TF_ONE_WAY); bool pending_async = false; + bool retry = false; BUG_ON(!node); - binder_node_lock(node); + +set_thread_prio: node_prio.prio = node->min_priority; node_prio.sched_policy = node->sched_policy; + if (thread) { + /* + * Priority must be set outside of lock, but must be + * done before enqueuing the transaction. + */ + binder_transaction_priority(thread->task, t, node_prio, + node->inherit_rt); + } + +retry_after_prio_restore: + binder_node_lock(node); if (oneway) { - BUG_ON(thread); + BUG_ON(!retry && thread); if (node->has_async_transaction) { pending_async = true; } else { node->has_async_transaction = true; } + if (thread && pending_async) { + /* + * The node state has changed since we selected + * the thread. Return the thread to the + * waiting_threads list. We have to drop + * the node lock to restore priority so we + * have to re-check the node state. + */ + binder_node_unlock(node); + binder_restore_priority(thread->task, + proc->default_priority); + binder_inner_proc_lock(proc); + list_add(&thread->waiting_thread_node, + &proc->waiting_threads); + binder_inner_proc_unlock(proc); + thread = NULL; + goto retry_after_prio_restore; + } } binder_inner_proc_lock(proc); @@ -2938,18 +2965,24 @@ static bool binder_proc_transaction(struct binder_transaction *t, return false; } - if (!thread && !pending_async) + if (!thread && !pending_async) { thread = binder_select_thread_ilocked(proc); + if (thread) { + if (oneway) + node->has_async_transaction = false; + binder_inner_proc_unlock(proc); + binder_node_unlock(node); + retry = true; + goto set_thread_prio; + } + } - if (thread) { - binder_transaction_priority(thread->task, t, node_prio, - node->inherit_rt); + if (thread) binder_enqueue_thread_work_ilocked(thread, &t->work); - } else if (!pending_async) { + else if (!pending_async) binder_enqueue_work_ilocked(&t->work, &proc->todo); - } else { + else binder_enqueue_work_ilocked(&t->work, &node->async_todo); - } if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); @@ -5347,9 +5380,6 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) if (proc->tsk != current->group_leader) return -EINVAL; - if ((vma->vm_end - vma->vm_start) > SZ_4M) - vma->vm_end = vma->vm_start + SZ_4M; - binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", __func__, proc->pid, vma->vm_start, vma->vm_end, diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index d42a8b2f636a5bbdcd43bcfee43b24d820e1e745..eb76a823fbb200f008b0e4c6ad02bc5818929857 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "binder_alloc.h" #include "binder_trace.h" @@ -689,7 +690,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, alloc->buffer = (void __user *)vma->vm_start; mutex_unlock(&binder_alloc_mmap_lock); - alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE, + alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start, + SZ_4M); + alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE, sizeof(alloc->pages[0]), GFP_KERNEL); if (alloc->pages == NULL) { @@ -697,7 +700,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, failure_string = "alloc page array"; goto err_alloc_pages_failed; } - alloc->buffer_size = vma->vm_end - vma->vm_start; buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) { diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index dd92faf197d5ed81a8a7c0fcbc0d39a73be5b977..05c2b32dcc4dcd97a15d7ffb0ea4896caf54c5b3 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1600,7 +1600,9 @@ static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hp */ if (!id || id->vendor != PCI_VENDOR_ID_INTEL) return; - if (((enum board_ids) id->driver_data) < board_ahci_pcs7) + + /* Skip applying the quirk on Denverton and beyond */ + if (((enum board_ids) id->driver_data) >= board_ahci_pcs7) return; /* diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index e742780950de84c330c2c83b1daf1a0905f03ed0..8befce036af84810b0a3c815829b87f6fd904d8c 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -153,17 +153,13 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv) { int rc, i; - if (hpriv->ahci_regulator) { - rc = regulator_enable(hpriv->ahci_regulator); - if (rc) - return rc; - } + rc = regulator_enable(hpriv->ahci_regulator); + if (rc) + return rc; - if (hpriv->phy_regulator) { - rc = regulator_enable(hpriv->phy_regulator); - if (rc) - goto disable_ahci_pwrs; - } + rc = regulator_enable(hpriv->phy_regulator); + if (rc) + goto disable_ahci_pwrs; for (i = 0; i < hpriv->nports; i++) { if (!hpriv->target_pwrs[i]) @@ -181,11 +177,9 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv) if (hpriv->target_pwrs[i]) regulator_disable(hpriv->target_pwrs[i]); - if (hpriv->phy_regulator) - regulator_disable(hpriv->phy_regulator); + regulator_disable(hpriv->phy_regulator); disable_ahci_pwrs: - if (hpriv->ahci_regulator) - regulator_disable(hpriv->ahci_regulator); + regulator_disable(hpriv->ahci_regulator); return rc; } EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators); @@ -207,10 +201,8 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv) regulator_disable(hpriv->target_pwrs[i]); } - if (hpriv->ahci_regulator) - regulator_disable(hpriv->ahci_regulator); - if (hpriv->phy_regulator) - regulator_disable(hpriv->phy_regulator); + regulator_disable(hpriv->ahci_regulator); + regulator_disable(hpriv->phy_regulator); } EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators); /** @@ -359,7 +351,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port, struct regulator *target_pwr; int rc = 0; - target_pwr = regulator_get_optional(dev, "target"); + target_pwr = regulator_get(dev, "target"); if (!IS_ERR(target_pwr)) hpriv->target_pwrs[port] = target_pwr; @@ -436,16 +428,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, hpriv->clks[i] = clk; } - hpriv->ahci_regulator = devm_regulator_get_optional(dev, "ahci"); + hpriv->ahci_regulator = devm_regulator_get(dev, "ahci"); if (IS_ERR(hpriv->ahci_regulator)) { rc = PTR_ERR(hpriv->ahci_regulator); - if (rc == -EPROBE_DEFER) + if (rc != 0) goto err_out; - rc = 0; - hpriv->ahci_regulator = NULL; } - hpriv->phy_regulator = devm_regulator_get_optional(dev, "phy"); + hpriv->phy_regulator = devm_regulator_get(dev, "phy"); if (IS_ERR(hpriv->phy_regulator)) { rc = PTR_ERR(hpriv->phy_regulator); if (rc == -EPROBE_DEFER) diff --git a/drivers/base/core.c b/drivers/base/core.c index acbf0b1414abf65cea2b1c44a18006a33137df44..e6d3e6d485daab3d8801b887df111a609ac34064 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -130,6 +131,9 @@ static int device_is_dependent(struct device *dev, void *target) return ret; list_for_each_entry(link, &dev->links.consumers, s_node) { + if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + continue; + if (link->consumer == target) return 1; @@ -199,8 +203,11 @@ static int device_reorder_to_tail(struct device *dev, void *not_used) device_pm_move_last(dev); device_for_each_child(dev, NULL, device_reorder_to_tail); - list_for_each_entry(link, &dev->links.consumers, s_node) + list_for_each_entry(link, &dev->links.consumers, s_node) { + if (link->flags == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + continue; device_reorder_to_tail(link->consumer, NULL); + } return 0; } @@ -227,7 +234,8 @@ void device_pm_move_to_tail(struct device *dev) #define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ DL_FLAG_AUTOREMOVE_SUPPLIER | \ - DL_FLAG_AUTOPROBE_CONSUMER) + DL_FLAG_AUTOPROBE_CONSUMER | \ + DL_FLAG_SYNC_STATE_ONLY) #define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \ DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE) @@ -295,6 +303,8 @@ struct device_link *device_link_add(struct device *consumer, if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || + (flags & DL_FLAG_SYNC_STATE_ONLY && + flags != DL_FLAG_SYNC_STATE_ONLY) || (flags & DL_FLAG_AUTOPROBE_CONSUMER && flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER))) @@ -315,11 +325,14 @@ struct device_link *device_link_add(struct device *consumer, /* * If the supplier has not been fully registered yet or there is a - * reverse dependency between the consumer and the supplier already in - * the graph, return NULL. + * reverse (non-SYNC_STATE_ONLY) dependency between the consumer and + * the supplier already in the graph, return NULL. If the link is a + * SYNC_STATE_ONLY link, we don't check for reverse dependencies + * because it only affects sync_state() callbacks. */ if (!device_pm_initialized(supplier) - || device_is_dependent(consumer, supplier)) { + || (!(flags & DL_FLAG_SYNC_STATE_ONLY) && + device_is_dependent(consumer, supplier))) { link = NULL; goto out; } @@ -346,9 +359,14 @@ struct device_link *device_link_add(struct device *consumer, } if (flags & DL_FLAG_STATELESS) { - link->flags |= DL_FLAG_STATELESS; kref_get(&link->kref); - goto out; + if (link->flags & DL_FLAG_SYNC_STATE_ONLY && + !(link->flags & DL_FLAG_STATELESS)) { + link->flags |= DL_FLAG_STATELESS; + goto reorder; + } else { + goto out; + } } /* @@ -370,6 +388,12 @@ struct device_link *device_link_add(struct device *consumer, link->flags |= DL_FLAG_MANAGED; device_link_init_status(link, consumer, supplier); } + if (link->flags & DL_FLAG_SYNC_STATE_ONLY && + !(flags & DL_FLAG_SYNC_STATE_ONLY)) { + link->flags &= ~DL_FLAG_SYNC_STATE_ONLY; + goto reorder; + } + goto out; } @@ -409,6 +433,13 @@ struct device_link *device_link_add(struct device *consumer, flags & DL_FLAG_PM_RUNTIME) pm_runtime_resume(supplier); + if (flags & DL_FLAG_SYNC_STATE_ONLY) { + dev_dbg(consumer, + "Linked as a sync state only consumer to %s\n", + dev_name(supplier)); + goto out; + } +reorder: /* * Move the consumer and all of the devices depending on it to the end * of dpm_list and the devices_kset list. @@ -449,13 +480,25 @@ EXPORT_SYMBOL_GPL(device_link_add); * This function is NOT meant to be called from the probe function of the * consumer but rather from code that creates/adds the consumer device. */ -static void device_link_wait_for_supplier(struct device *consumer) +static void device_link_wait_for_supplier(struct device *consumer, + bool need_for_probe) { mutex_lock(&wfs_lock); list_add_tail(&consumer->links.needs_suppliers, &wait_for_suppliers); + consumer->links.need_for_probe = need_for_probe; mutex_unlock(&wfs_lock); } +static void device_link_wait_for_mandatory_supplier(struct device *consumer) +{ + device_link_wait_for_supplier(consumer, true); +} + +static void device_link_wait_for_optional_supplier(struct device *consumer) +{ + device_link_wait_for_supplier(consumer, false); +} + /** * device_link_add_missing_supplier_links - Add links from consumer devices to * supplier devices, leaving any @@ -625,7 +668,8 @@ int device_links_check_suppliers(struct device *dev) * probe. */ mutex_lock(&wfs_lock); - if (!list_empty(&dev->links.needs_suppliers)) { + if (!list_empty(&dev->links.needs_suppliers) && + dev->links.need_for_probe) { mutex_unlock(&wfs_lock); return -EPROBE_DEFER; } @@ -634,7 +678,8 @@ int device_links_check_suppliers(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.suppliers, c_node) { - if (!(link->flags & DL_FLAG_MANAGED)) + if (!(link->flags & DL_FLAG_MANAGED) || + link->flags & DL_FLAG_SYNC_STATE_ONLY) continue; if (link->status != DL_STATE_AVAILABLE) { @@ -728,6 +773,15 @@ void device_links_driver_bound(struct device *dev) { struct device_link *link; + /* + * If a device probes successfully, it's expected to have created all + * the device links it needs to or make new device links as it needs + * them. So, it no longer needs to wait on any suppliers. + */ + mutex_lock(&wfs_lock); + list_del_init(&dev->links.needs_suppliers); + mutex_unlock(&wfs_lock); + device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { @@ -948,7 +1002,8 @@ void device_links_unbind_consumers(struct device *dev) list_for_each_entry(link, &dev->links.consumers, s_node) { enum device_link_state status; - if (!(link->flags & DL_FLAG_MANAGED)) + if (!(link->flags & DL_FLAG_MANAGED) || + link->flags & DL_FLAG_SYNC_STATE_ONLY) continue; status = link->status; @@ -2242,7 +2297,7 @@ int device_add(struct device *dev) struct device *parent; struct kobject *kobj; struct class_interface *class_intf; - int error = -EINVAL; + int error = -EINVAL, fw_ret; struct kobject *glue_dir = NULL; dev = get_device(dev); @@ -2358,9 +2413,13 @@ int device_add(struct device *dev) */ device_link_add_missing_supplier_links(); - if (fwnode_has_op(dev->fwnode, add_links) - && fwnode_call_int_op(dev->fwnode, add_links, dev)) - device_link_wait_for_supplier(dev); + if (fwnode_has_op(dev->fwnode, add_links)) { + fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev); + if (fw_ret == -ENODEV) + device_link_wait_for_mandatory_supplier(dev); + else if (fw_ret) + device_link_wait_for_optional_supplier(dev); + } bus_probe_device(dev); if (parent) @@ -3346,6 +3405,8 @@ void device_shutdown(void) wait_for_device_probe(); device_block_probing(); + cpufreq_suspend(); + spin_lock(&devices_kset->list_lock); /* * Walk the devices list backward, shutting down each in turn. diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 6bea4f3f8040dd77c87cf34647b26515061a76a1..55907c27075b13295c05ed197fa7f087546452d1 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -540,6 +540,9 @@ static ssize_t soft_offline_page_store(struct device *dev, pfn >>= PAGE_SHIFT; if (!pfn_valid(pfn)) return -ENXIO; + /* Only online pages can be soft-offlined (esp., not ZONE_DEVICE). */ + if (!pfn_to_online_page(pfn)) + return -EIO; ret = soft_offline_page(pfn_to_page(pfn), 0); return ret == 0 ? count : ret; } diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 6c90fd7e2ff8f385a7c00fa6a36bf4d3a344b02d..350dcafd751f8e6c352f5e68945103da7cd84227 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -115,20 +115,10 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type) spin_lock_irqsave(&dev->power.lock, flags); - switch (type) { - case DEV_PM_QOS_RESUME_LATENCY: + if (type == DEV_PM_QOS_RESUME_LATENCY) { ret = IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT : pm_qos_read_value(&qos->resume_latency); - break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE - : pm_qos_read_value(&qos->min_frequency); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE - : pm_qos_read_value(&qos->max_frequency); - break; - default: + } else { WARN_ON(1); ret = 0; } @@ -169,14 +159,6 @@ static int apply_constraint(struct dev_pm_qos_request *req, req->dev->power.set_latency_tolerance(req->dev, value); } break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = pm_qos_update_target(&qos->min_frequency, - &req->data.pnode, action, value); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = pm_qos_update_target(&qos->max_frequency, - &req->data.pnode, action, value); - break; case DEV_PM_QOS_FLAGS: ret = pm_qos_update_flags(&qos->flags, &req->data.flr, action, value); @@ -227,24 +209,6 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; c->type = PM_QOS_MIN; - c = &qos->min_frequency; - plist_head_init(&c->list); - c->target_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; - c->default_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; - c->no_constraint_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; - c->type = PM_QOS_MAX; - c->notifiers = ++n; - BLOCKING_INIT_NOTIFIER_HEAD(n); - - c = &qos->max_frequency; - plist_head_init(&c->list); - c->target_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; - c->default_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; - c->no_constraint_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; - c->type = PM_QOS_MIN; - c->notifiers = ++n; - BLOCKING_INIT_NOTIFIER_HEAD(n); - INIT_LIST_HEAD(&qos->flags.list); spin_lock_irq(&dev->power.lock); @@ -305,18 +269,6 @@ void dev_pm_qos_constraints_destroy(struct device *dev) memset(req, 0, sizeof(*req)); } - c = &qos->min_frequency; - plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { - apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE); - memset(req, 0, sizeof(*req)); - } - - c = &qos->max_frequency; - plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) { - apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); - memset(req, 0, sizeof(*req)); - } - f = &qos->flags; list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) { apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); @@ -428,8 +380,6 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, switch(req->type) { case DEV_PM_QOS_RESUME_LATENCY: case DEV_PM_QOS_LATENCY_TOLERANCE: - case DEV_PM_QOS_MIN_FREQUENCY: - case DEV_PM_QOS_MAX_FREQUENCY: curr_value = req->data.pnode.prio; break; case DEV_PM_QOS_FLAGS: @@ -557,14 +507,6 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier, ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers, notifier); break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = blocking_notifier_chain_register(dev->power.qos->min_frequency.notifiers, - notifier); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = blocking_notifier_chain_register(dev->power.qos->max_frequency.notifiers, - notifier); - break; default: WARN_ON(1); ret = -EINVAL; @@ -604,14 +546,6 @@ int dev_pm_qos_remove_notifier(struct device *dev, ret = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers, notifier); break; - case DEV_PM_QOS_MIN_FREQUENCY: - ret = blocking_notifier_chain_unregister(dev->power.qos->min_frequency.notifiers, - notifier); - break; - case DEV_PM_QOS_MAX_FREQUENCY: - ret = blocking_notifier_chain_unregister(dev->power.qos->max_frequency.notifiers, - notifier); - break; default: WARN_ON(1); ret = -EINVAL; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 478aa86fc1f28d9fd39bd3b0b6c7b5ba15de897b..a94ee45440b3b6443ab9921d6a7e2e250e9146bf 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -385,17 +385,16 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, struct nbd_device *nbd = cmd->nbd; struct nbd_config *config; + if (!mutex_trylock(&cmd->lock)) + return BLK_EH_RESET_TIMER; + if (!refcount_inc_not_zero(&nbd->config_refs)) { cmd->status = BLK_STS_TIMEOUT; + mutex_unlock(&cmd->lock); goto done; } config = nbd->config; - if (!mutex_trylock(&cmd->lock)) { - nbd_config_put(nbd); - return BLK_EH_RESET_TIMER; - } - if (config->num_connections > 1) { dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out, retrying (%d/%d alive)\n", @@ -711,6 +710,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) ret = -ENOENT; goto out; } + if (cmd->status != BLK_STS_OK) { + dev_err(disk_to_dev(nbd->disk), "Command already handled %p\n", + req); + ret = -ENOENT; + goto out; + } if (test_bit(NBD_CMD_REQUEUED, &cmd->flags)) { dev_err(disk_to_dev(nbd->disk), "Raced with timeout on req %p\n", req); @@ -792,7 +797,10 @@ static bool nbd_clear_req(struct request *req, void *data, bool reserved) { struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req); + mutex_lock(&cmd->lock); cmd->status = BLK_STS_IOERR; + mutex_unlock(&cmd->lock); + blk_mq_complete_request(req); return true; } @@ -972,6 +980,25 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx, return ret; } +static struct socket *nbd_get_socket(struct nbd_device *nbd, unsigned long fd, + int *err) +{ + struct socket *sock; + + *err = 0; + sock = sockfd_lookup(fd, err); + if (!sock) + return NULL; + + if (sock->ops->shutdown == sock_no_shutdown) { + dev_err(disk_to_dev(nbd->disk), "Unsupported socket: shutdown callout must be supported.\n"); + *err = -EINVAL; + return NULL; + } + + return sock; +} + static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, bool netlink) { @@ -981,7 +1008,7 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, struct nbd_sock *nsock; int err; - sock = sockfd_lookup(arg, &err); + sock = nbd_get_socket(nbd, arg, &err); if (!sock) return err; @@ -1033,7 +1060,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) int i; int err; - sock = sockfd_lookup(arg, &err); + sock = nbd_get_socket(nbd, arg, &err); if (!sock) return err; diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 7c4350c0fb77e6ba5366bf4455ecb8f410484499..39136675dae5b381241a3ae2acce1cd93e2cfa39 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -6639,10 +6639,13 @@ static int rbd_add_acquire_lock(struct rbd_device *rbd_dev) queue_delayed_work(rbd_dev->task_wq, &rbd_dev->lock_dwork, 0); ret = wait_for_completion_killable_timeout(&rbd_dev->acquire_wait, ceph_timeout_jiffies(rbd_dev->opts->lock_timeout)); - if (ret > 0) + if (ret > 0) { ret = rbd_dev->acquire_err; - else if (!ret) - ret = -ETIMEDOUT; + } else { + cancel_delayed_work_sync(&rbd_dev->lock_dwork); + if (!ret) + ret = -ETIMEDOUT; + } if (ret) { rbd_warn(rbd_dev, "failed to acquire exclusive lock: %ld", ret); diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index d58a359a66225f39682c067739eb9843bae36b80..4285e75e52c3424b7aa2063cd202509647c5d20a 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -413,13 +413,14 @@ static void reset_bdev(struct zram *zram) static ssize_t backing_dev_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct file *file; struct zram *zram = dev_to_zram(dev); - struct file *file = zram->backing_dev; char *p; ssize_t ret; down_read(&zram->init_lock); - if (!zram->backing_dev) { + file = zram->backing_dev; + if (!file) { memcpy(buf, "none\n", 5); up_read(&zram->init_lock); return 5; diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index ad50efb470aaa296bdc9cae1ba7a3ea321ddcf1c..2b6670daf7fc70cd58ac287785d06990bf1cb61e 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -74,6 +74,7 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { * @clk_disable_quirk: module specific clock disable quirk * @reset_done_quirk: module specific reset done quirk * @module_enable_quirk: module specific enable quirk + * @module_disable_quirk: module specific disable quirk */ struct sysc { struct device *dev; @@ -100,6 +101,7 @@ struct sysc { void (*clk_disable_quirk)(struct sysc *sysc); void (*reset_done_quirk)(struct sysc *sysc); void (*module_enable_quirk)(struct sysc *sysc); + void (*module_disable_quirk)(struct sysc *sysc); }; static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, @@ -959,6 +961,9 @@ static int sysc_disable_module(struct device *dev) if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) return 0; + if (ddata->module_disable_quirk) + ddata->module_disable_quirk(ddata); + regbits = ddata->cap->regbits; reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); @@ -1248,6 +1253,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_MODULE_QUIRK_SGX), SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, SYSC_MODULE_QUIRK_WDT), + /* Watchdog on am3 and am4 */ + SYSC_QUIRK("wdt", 0x44e35000, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, + SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE), #ifdef DEBUG SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), @@ -1440,14 +1448,14 @@ static void sysc_reset_done_quirk_wdt(struct sysc *ddata) !(val & 0x10), 100, MAX_MODULE_SOFTRESET_WAIT); if (error) - dev_warn(ddata->dev, "wdt disable spr failed\n"); + dev_warn(ddata->dev, "wdt disable step1 failed\n"); - sysc_write(ddata, wps, 0x5555); + sysc_write(ddata, spr, 0x5555); error = readl_poll_timeout(ddata->module_va + wps, val, !(val & 0x10), 100, MAX_MODULE_SOFTRESET_WAIT); if (error) - dev_warn(ddata->dev, "wdt disable wps failed\n"); + dev_warn(ddata->dev, "wdt disable step2 failed\n"); } static void sysc_init_module_quirks(struct sysc *ddata) @@ -1471,8 +1479,10 @@ static void sysc_init_module_quirks(struct sysc *ddata) if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_SGX) ddata->module_enable_quirk = sysc_module_enable_quirk_sgx; - if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT) + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT) { ddata->reset_done_quirk = sysc_reset_done_quirk_wdt; + ddata->module_disable_quirk = sysc_reset_done_quirk_wdt; + } } static int sysc_clockdomain_init(struct sysc *ddata) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index f711715aa5797d4d7a92d82ec6e5a961bf230544..2075100319fb68dcec9fab32861d5361bf32390c 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -229,6 +229,15 @@ config CPUFREQ_DT_PLATDEV If in doubt, say N. +config CPUFREQ_DUMMY + tristate "Dummy CPU frequency driver" + help + This option adds a generic dummy CPUfreq driver, which sets a fake + 2-frequency table when initializing each policy and otherwise does + nothing. + + If in doubt, say N + if X86 source "drivers/cpufreq/Kconfig.x86" endif diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 93d52a112cab2d3023420ccfdbf82fe0d05255f1..33d6b64f9203e25cfc61bb341a7827f1a2ff93b4 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -20,6 +20,8 @@ obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o +obj-$(CONFIG_CPUFREQ_DUMMY) += dummy-cpufreq.o + ################################################################################## # x86 drivers. # Link order matters. K8 is preferred to ACPI because of firmware bugs in early diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9c15d7f52e1cc5203569a9f12efc8e757a5512bf..37e9092284de8f819c06193841a34861deb978a6 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -728,7 +728,7 @@ static ssize_t store_##file_name \ if (ret != 1) \ return -EINVAL; \ \ - ret = dev_pm_qos_update_request(policy->object##_freq_req, val);\ + ret = freq_qos_update_request(policy->object##_freq_req, val);\ return ret >= 0 ? count : ret; \ } @@ -1210,19 +1210,21 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) goto err_free_real_cpus; } + freq_constraints_init(&policy->constraints); + policy->nb_min.notifier_call = cpufreq_notifier_min; policy->nb_max.notifier_call = cpufreq_notifier_max; - ret = dev_pm_qos_add_notifier(dev, &policy->nb_min, - DEV_PM_QOS_MIN_FREQUENCY); + ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MIN, + &policy->nb_min); if (ret) { dev_err(dev, "Failed to register MIN QoS notifier: %d (%*pbl)\n", ret, cpumask_pr_args(policy->cpus)); goto err_kobj_remove; } - ret = dev_pm_qos_add_notifier(dev, &policy->nb_max, - DEV_PM_QOS_MAX_FREQUENCY); + ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MAX, + &policy->nb_max); if (ret) { dev_err(dev, "Failed to register MAX QoS notifier: %d (%*pbl)\n", ret, cpumask_pr_args(policy->cpus)); @@ -1240,8 +1242,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) return policy; err_min_qos_notifier: - dev_pm_qos_remove_notifier(dev, &policy->nb_min, - DEV_PM_QOS_MIN_FREQUENCY); + freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MIN, + &policy->nb_min); err_kobj_remove: cpufreq_policy_put_kobj(policy); err_free_real_cpus: @@ -1258,7 +1260,6 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) static void cpufreq_policy_free(struct cpufreq_policy *policy) { - struct device *dev = get_cpu_device(policy->cpu); unsigned long flags; int cpu; @@ -1270,10 +1271,13 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) per_cpu(cpufreq_cpu_data, cpu) = NULL; write_unlock_irqrestore(&cpufreq_driver_lock, flags); - dev_pm_qos_remove_notifier(dev, &policy->nb_max, - DEV_PM_QOS_MAX_FREQUENCY); - dev_pm_qos_remove_notifier(dev, &policy->nb_min, - DEV_PM_QOS_MIN_FREQUENCY); + freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MAX, + &policy->nb_max); + freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MIN, + &policy->nb_min); + + /* Cancel any pending policy->update work before freeing the policy. */ + cancel_work_sync(&policy->update); if (policy->max_freq_req) { /* @@ -1282,10 +1286,10 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) */ blocking_notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_REMOVE_POLICY, policy); - dev_pm_qos_remove_request(policy->max_freq_req); + freq_qos_remove_request(policy->max_freq_req); } - dev_pm_qos_remove_request(policy->min_freq_req); + freq_qos_remove_request(policy->min_freq_req); kfree(policy->min_freq_req); cpufreq_policy_put_kobj(policy); @@ -1365,8 +1369,6 @@ static int cpufreq_online(unsigned int cpu) cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); if (new_policy) { - struct device *dev = get_cpu_device(cpu); - for_each_cpu(j, policy->related_cpus) { per_cpu(cpufreq_cpu_data, j) = policy; add_cpu_dev_symlink(policy, j); @@ -1377,36 +1379,31 @@ static int cpufreq_online(unsigned int cpu) if (!policy->min_freq_req) goto out_destroy_policy; - ret = dev_pm_qos_add_request(dev, policy->min_freq_req, - DEV_PM_QOS_MIN_FREQUENCY, - policy->min); + ret = freq_qos_add_request(&policy->constraints, + policy->min_freq_req, FREQ_QOS_MIN, + policy->min); if (ret < 0) { /* - * So we don't call dev_pm_qos_remove_request() for an + * So we don't call freq_qos_remove_request() for an * uninitialized request. */ kfree(policy->min_freq_req); policy->min_freq_req = NULL; - - dev_err(dev, "Failed to add min-freq constraint (%d)\n", - ret); goto out_destroy_policy; } /* * This must be initialized right here to avoid calling - * dev_pm_qos_remove_request() on uninitialized request in case + * freq_qos_remove_request() on uninitialized request in case * of errors. */ policy->max_freq_req = policy->min_freq_req + 1; - ret = dev_pm_qos_add_request(dev, policy->max_freq_req, - DEV_PM_QOS_MAX_FREQUENCY, - policy->max); + ret = freq_qos_add_request(&policy->constraints, + policy->max_freq_req, FREQ_QOS_MAX, + policy->max); if (ret < 0) { policy->max_freq_req = NULL; - dev_err(dev, "Failed to add max-freq constraint (%d)\n", - ret); goto out_destroy_policy; } @@ -2389,7 +2386,6 @@ int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy) { struct cpufreq_governor *old_gov; - struct device *cpu_dev = get_cpu_device(policy->cpu); int ret; pr_debug("setting new policy for CPU %u: %u - %u kHz\n", @@ -2401,8 +2397,8 @@ int cpufreq_set_policy(struct cpufreq_policy *policy, * PM QoS framework collects all the requests from users and provide us * the final aggregated value here. */ - new_policy->min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY); - new_policy->max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY); + new_policy->min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN); + new_policy->max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX); /* verify the cpu speed can be set within this limit */ ret = cpufreq_driver->verify(new_policy); @@ -2535,7 +2531,7 @@ static int cpufreq_boost_set_sw(int state) break; } - ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max); + ret = freq_qos_update_request(policy->max_freq_req, policy->max); if (ret < 0) break; } @@ -2754,14 +2750,6 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) } EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); -/* - * Stop cpufreq at shutdown to make sure it isn't holding any locks - * or mutexes when secondary CPUs are halted. - */ -static struct syscore_ops cpufreq_syscore_ops = { - .shutdown = cpufreq_suspend, -}; - struct kobject *cpufreq_global_kobject; EXPORT_SYMBOL(cpufreq_global_kobject); @@ -2773,8 +2761,6 @@ static int __init cpufreq_core_init(void) cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj); BUG_ON(!cpufreq_global_kobject); - register_syscore_ops(&cpufreq_syscore_ops); - return 0; } module_param(off, int, 0444); diff --git a/drivers/cpufreq/dummy-cpufreq.c b/drivers/cpufreq/dummy-cpufreq.c new file mode 100644 index 0000000000000000000000000000000000000000..ea40d5c7a9fa75cd674e8f0b7fb37dfa9d4dc317 --- /dev/null +++ b/drivers/cpufreq/dummy-cpufreq.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Google, Inc. + */ +#include +#include + +static struct cpufreq_frequency_table freq_table[] = { + { .frequency = 1 }, + { .frequency = 2 }, + { .frequency = CPUFREQ_TABLE_END }, +}; + +static int dummy_cpufreq_target_index(struct cpufreq_policy *policy, + unsigned int index) +{ + return 0; +} + +static int dummy_cpufreq_driver_init(struct cpufreq_policy *policy) +{ + policy->freq_table = freq_table; + return 0; +} + +static unsigned int dummy_cpufreq_get(unsigned int cpu) +{ + return 1; +} + +static int dummy_cpufreq_verify(struct cpufreq_policy *policy) +{ + return 0; +} + +static struct cpufreq_driver dummy_cpufreq_driver = { + .name = "dummy", + .target_index = dummy_cpufreq_target_index, + .init = dummy_cpufreq_driver_init, + .get = dummy_cpufreq_get, + .verify = dummy_cpufreq_verify, + .attr = cpufreq_generic_attr, +}; + +static int __init dummy_cpufreq_init(void) +{ + return cpufreq_register_driver(&dummy_cpufreq_driver); +} + +static void __exit dummy_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&dummy_cpufreq_driver); +} + +module_init(dummy_cpufreq_init); +module_exit(dummy_cpufreq_exit); + +MODULE_AUTHOR("Connor O'Brien "); +MODULE_DESCRIPTION("dummy cpufreq driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 9f02de9a1b4743ea7d01c2a3ff9f85e0cb81a997..53a51c169451f7f71f1f99652a42cb5532aa5963 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1088,10 +1088,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b, static struct cpufreq_driver intel_pstate; -static void update_qos_request(enum dev_pm_qos_req_type type) +static void update_qos_request(enum freq_qos_req_type type) { int max_state, turbo_max, freq, i, perf_pct; - struct dev_pm_qos_request *req; + struct freq_qos_request *req; struct cpufreq_policy *policy; for_each_possible_cpu(i) { @@ -1112,7 +1112,7 @@ static void update_qos_request(enum dev_pm_qos_req_type type) else turbo_max = cpu->pstate.turbo_pstate; - if (type == DEV_PM_QOS_MIN_FREQUENCY) { + if (type == FREQ_QOS_MIN) { perf_pct = global.min_perf_pct; } else { req++; @@ -1122,7 +1122,7 @@ static void update_qos_request(enum dev_pm_qos_req_type type) freq = DIV_ROUND_UP(turbo_max * perf_pct, 100); freq *= cpu->pstate.scaling; - if (dev_pm_qos_update_request(req, freq) < 0) + if (freq_qos_update_request(req, freq) < 0) pr_warn("Failed to update freq constraint: CPU%d\n", i); } } @@ -1153,7 +1153,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, if (intel_pstate_driver == &intel_pstate) intel_pstate_update_policies(); else - update_qos_request(DEV_PM_QOS_MAX_FREQUENCY); + update_qos_request(FREQ_QOS_MAX); mutex_unlock(&intel_pstate_driver_lock); @@ -1187,7 +1187,7 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct kobj_attribute *b, if (intel_pstate_driver == &intel_pstate) intel_pstate_update_policies(); else - update_qos_request(DEV_PM_QOS_MIN_FREQUENCY); + update_qos_request(FREQ_QOS_MIN); mutex_unlock(&intel_pstate_driver_lock); @@ -2381,7 +2381,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy, static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) { int max_state, turbo_max, min_freq, max_freq, ret; - struct dev_pm_qos_request *req; + struct freq_qos_request *req; struct cpudata *cpu; struct device *dev; @@ -2416,15 +2416,15 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) max_freq = DIV_ROUND_UP(turbo_max * global.max_perf_pct, 100); max_freq *= cpu->pstate.scaling; - ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_MIN_FREQUENCY, - min_freq); + ret = freq_qos_add_request(&policy->constraints, req, FREQ_QOS_MIN, + min_freq); if (ret < 0) { dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret); goto free_req; } - ret = dev_pm_qos_add_request(dev, req + 1, DEV_PM_QOS_MAX_FREQUENCY, - max_freq); + ret = freq_qos_add_request(&policy->constraints, req + 1, FREQ_QOS_MAX, + max_freq); if (ret < 0) { dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret); goto remove_min_req; @@ -2435,7 +2435,7 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) return 0; remove_min_req: - dev_pm_qos_remove_request(req); + freq_qos_remove_request(req); free_req: kfree(req); pstate_exit: @@ -2446,12 +2446,12 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy) static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy) { - struct dev_pm_qos_request *req; + struct freq_qos_request *req; req = policy->driver_data; - dev_pm_qos_remove_request(req + 1); - dev_pm_qos_remove_request(req); + freq_qos_remove_request(req + 1); + freq_qos_remove_request(req); kfree(req); return intel_pstate_cpu_exit(policy); diff --git a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c index bc9dd30395c402893d2ca71a5b78a96888c3526e..037fe23bc6ed0feeb76384126706a24cab82b863 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c @@ -65,7 +65,7 @@ EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi); static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg) { struct cpufreq_policy *policy; - struct dev_pm_qos_request *req; + struct freq_qos_request *req; u8 node, slow_mode; int cpu, ret; @@ -86,7 +86,7 @@ static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg) req = policy->driver_data; - ret = dev_pm_qos_update_request(req, + ret = freq_qos_update_request(req, policy->freq_table[slow_mode].frequency); if (ret < 0) pr_warn("Failed to update freq constraint: %d\n", ret); @@ -103,7 +103,7 @@ static struct pmi_handler cbe_pmi_handler = { void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy) { - struct dev_pm_qos_request *req; + struct freq_qos_request *req; int ret; if (!cbe_cpufreq_has_pmi) @@ -113,9 +113,8 @@ void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy) if (!req) return; - ret = dev_pm_qos_add_request(get_cpu_device(policy->cpu), req, - DEV_PM_QOS_MAX_FREQUENCY, - policy->freq_table[0].frequency); + ret = freq_qos_add_request(&policy->constraints, req, FREQ_QOS_MAX, + policy->freq_table[0].frequency); if (ret < 0) { pr_err("Failed to add freq constraint (%d)\n", ret); kfree(req); @@ -128,10 +127,10 @@ EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_init); void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy) { - struct dev_pm_qos_request *req = policy->driver_data; + struct freq_qos_request *req = policy->driver_data; if (cbe_cpufreq_has_pmi) { - dev_pm_qos_remove_request(req); + freq_qos_remove_request(req); kfree(req); } } diff --git a/drivers/cpuidle/cpuidle-haltpoll.c b/drivers/cpuidle/cpuidle-haltpoll.c index 932390b028f1df148d8f96bd6a5b1b6b36fcec72..b0ce9bc78113e6bde532101ffe0beba9c9baf860 100644 --- a/drivers/cpuidle/cpuidle-haltpoll.c +++ b/drivers/cpuidle/cpuidle-haltpoll.c @@ -95,6 +95,10 @@ static int __init haltpoll_init(void) int ret; struct cpuidle_driver *drv = &haltpoll_driver; + /* Do not load haltpoll if idle= is passed */ + if (boot_option_idle_override != IDLE_NO_OVERRIDE) + return -ENODEV; + cpuidle_poll_state_init(drv); if (!kvm_para_available() || diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c index 774d991d7cca49011016d41c00914ad84059ccb8..aca75237bbcf83eb1d440bcdf1e4d3b702cff0a1 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.c +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c @@ -1297,7 +1297,7 @@ static void make_established(struct sock *sk, u32 snd_isn, unsigned int opt) tp->write_seq = snd_isn; tp->snd_nxt = snd_isn; tp->snd_una = snd_isn; - inet_sk(sk)->inet_id = tp->write_seq ^ jiffies; + inet_sk(sk)->inet_id = prandom_u32(); assign_rxopt(sk, opt); if (tp->rcv_wnd > (RCV_BUFSIZ_M << 10)) diff --git a/drivers/crypto/chelsio/chtls/chtls_io.c b/drivers/crypto/chelsio/chtls/chtls_io.c index 0891ab829b1b6b1318353e945e6394fab29f7c1e..98bc5a4cd5e7014990f064a92777308ae98b13e4 100644 --- a/drivers/crypto/chelsio/chtls/chtls_io.c +++ b/drivers/crypto/chelsio/chtls/chtls_io.c @@ -1702,7 +1702,7 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, return peekmsg(sk, msg, len, nonblock, flags); if (sk_can_busy_loop(sk) && - skb_queue_empty(&sk->sk_receive_queue) && + skb_queue_empty_lockless(&sk->sk_receive_queue) && sk->sk_state == TCP_ESTABLISHED) sk_busy_loop(sk, nonblock); diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 42a8f3f1168133424091f35e011f58c2e757b890..709002515550cd2e6ff989a4c2bdd11b5b0cdf9c 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -471,7 +471,7 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj, if (pfence_excl) *pfence_excl = fence_excl; else if (fence_excl) - shared[++shared_count] = fence_excl; + shared[shared_count++] = fence_excl; if (!shared_count) { kfree(shared); diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 9ba74ab7e912e90fe78ab9f02b4120d79ab14fb4..c27e206a764c3599ef8e548c4d9491399ce70c13 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1707,6 +1707,14 @@ static void sdma_add_scripts(struct sdma_engine *sdma, if (!sdma->script_number) sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; + if (sdma->script_number > sizeof(struct sdma_script_start_addrs) + / sizeof(s32)) { + dev_err(sdma->dev, + "SDMA script number %d not match with firmware.\n", + sdma->script_number); + return; + } + for (i = 0; i < sdma->script_number; i++) if (addr_arr[i] > 0) saddr_arr[i] = addr_arr[i]; diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 8e90a405939df4989d69d001efc803515ca1515a..ef73f65224b1b7b3d419b7543478cfbb63da6c07 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -694,6 +694,25 @@ static int bam_dma_terminate_all(struct dma_chan *chan) /* remove all transactions, including active transaction */ spin_lock_irqsave(&bchan->vc.lock, flag); + /* + * If we have transactions queued, then some might be committed to the + * hardware in the desc fifo. The only way to reset the desc fifo is + * to do a hardware reset (either by pipe or the entire block). + * bam_chan_init_hw() will trigger a pipe reset, and also reinit the + * pipe. If the pipe is left disabled (default state after pipe reset) + * and is accessed by a connected hardware engine, a fatal error in + * the BAM will occur. There is a small window where this could happen + * with bam_chan_init_hw(), but it is assumed that the caller has + * stopped activity on any attached hardware engine. Make sure to do + * this first so that the BAM hardware doesn't cause memory corruption + * by accessing freed resources. + */ + if (!list_empty(&bchan->desc_list)) { + async_desc = list_first_entry(&bchan->desc_list, + struct bam_async_desc, desc_node); + bam_chan_init_hw(bchan, async_desc->dir); + } + list_for_each_entry_safe(async_desc, tmp, &bchan->desc_list, desc_node) { list_add(&async_desc->vd.node, &bchan->vc.desc_issued); diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 525dc7338fe3b86842f4d2aa3ffd9857d34ec5f6..8546ad03472083d76156995158e860e106be028b 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -134,6 +134,10 @@ #define SPRD_DMA_SRC_TRSF_STEP_OFFSET 0 #define SPRD_DMA_TRSF_STEP_MASK GENMASK(15, 0) +/* SPRD DMA_SRC_BLK_STEP register definition */ +#define SPRD_DMA_LLIST_HIGH_MASK GENMASK(31, 28) +#define SPRD_DMA_LLIST_HIGH_SHIFT 28 + /* define DMA channel mode & trigger mode mask */ #define SPRD_DMA_CHN_MODE_MASK GENMASK(7, 0) #define SPRD_DMA_TRG_MODE_MASK GENMASK(7, 0) @@ -208,6 +212,7 @@ struct sprd_dma_dev { struct sprd_dma_chn channels[0]; }; +static void sprd_dma_free_desc(struct virt_dma_desc *vd); static bool sprd_dma_filter_fn(struct dma_chan *chan, void *param); static struct of_dma_filter_info sprd_dma_info = { .filter_fn = sprd_dma_filter_fn, @@ -609,12 +614,19 @@ static int sprd_dma_alloc_chan_resources(struct dma_chan *chan) static void sprd_dma_free_chan_resources(struct dma_chan *chan) { struct sprd_dma_chn *schan = to_sprd_dma_chan(chan); + struct virt_dma_desc *cur_vd = NULL; unsigned long flags; spin_lock_irqsave(&schan->vc.lock, flags); + if (schan->cur_desc) + cur_vd = &schan->cur_desc->vd; + sprd_dma_stop(schan); spin_unlock_irqrestore(&schan->vc.lock, flags); + if (cur_vd) + sprd_dma_free_desc(cur_vd); + vchan_free_chan_resources(&schan->vc); pm_runtime_put(chan->device->dev); } @@ -717,6 +729,7 @@ static int sprd_dma_fill_desc(struct dma_chan *chan, u32 int_mode = flags & SPRD_DMA_INT_MASK; int src_datawidth, dst_datawidth, src_step, dst_step; u32 temp, fix_mode = 0, fix_en = 0; + phys_addr_t llist_ptr; if (dir == DMA_MEM_TO_DEV) { src_step = sprd_dma_get_step(slave_cfg->src_addr_width); @@ -814,13 +827,16 @@ static int sprd_dma_fill_desc(struct dma_chan *chan, * Set the link-list pointer point to next link-list * configuration's physical address. */ - hw->llist_ptr = schan->linklist.phy_addr + temp; + llist_ptr = schan->linklist.phy_addr + temp; + hw->llist_ptr = lower_32_bits(llist_ptr); + hw->src_blk_step = (upper_32_bits(llist_ptr) << SPRD_DMA_LLIST_HIGH_SHIFT) & + SPRD_DMA_LLIST_HIGH_MASK; } else { hw->llist_ptr = 0; + hw->src_blk_step = 0; } hw->frg_step = 0; - hw->src_blk_step = 0; hw->des_blk_step = 0; return 0; } @@ -1023,15 +1039,22 @@ static int sprd_dma_resume(struct dma_chan *chan) static int sprd_dma_terminate_all(struct dma_chan *chan) { struct sprd_dma_chn *schan = to_sprd_dma_chan(chan); + struct virt_dma_desc *cur_vd = NULL; unsigned long flags; LIST_HEAD(head); spin_lock_irqsave(&schan->vc.lock, flags); + if (schan->cur_desc) + cur_vd = &schan->cur_desc->vd; + sprd_dma_stop(schan); vchan_get_all_descriptors(&schan->vc, &head); spin_unlock_irqrestore(&schan->vc.lock, flags); + if (cur_vd) + sprd_dma_free_desc(cur_vd); + vchan_dma_desc_free_list(&schan->vc, &head); return 0; } diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index 5f8adf5c1f203f4c1905f728c752ed2dbbfe64b5..6e1268552f74070277e28ed1036df1b4349bca7b 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -40,6 +40,7 @@ #define ADMA_CH_CONFIG_MAX_BURST_SIZE 16 #define ADMA_CH_CONFIG_WEIGHT_FOR_WRR(val) ((val) & 0xf) #define ADMA_CH_CONFIG_MAX_BUFS 8 +#define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(reqs) (reqs << 4) #define ADMA_CH_FIFO_CTRL 0x2c #define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val) (((val) & 0xf) << 8) @@ -77,6 +78,7 @@ struct tegra_adma; * @ch_req_tx_shift: Register offset for AHUB transmit channel select. * @ch_req_rx_shift: Register offset for AHUB receive channel select. * @ch_base_offset: Register offset of DMA channel registers. + * @has_outstanding_reqs: If DMA channel can have outstanding requests. * @ch_fifo_ctrl: Default value for channel FIFO CTRL register. * @ch_req_mask: Mask for Tx or Rx channel select. * @ch_req_max: Maximum number of Tx or Rx channels available. @@ -95,6 +97,7 @@ struct tegra_adma_chip_data { unsigned int ch_req_max; unsigned int ch_reg_size; unsigned int nr_channels; + bool has_outstanding_reqs; }; /* @@ -594,6 +597,8 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, ADMA_CH_CTRL_FLOWCTRL_EN; ch_regs->config |= cdata->adma_get_burst_config(burst_size); ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1); + if (cdata->has_outstanding_reqs) + ch_regs->config |= TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(8); ch_regs->fifo_ctrl = cdata->ch_fifo_ctrl; ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK; @@ -778,6 +783,7 @@ static const struct tegra_adma_chip_data tegra210_chip_data = { .ch_req_tx_shift = 28, .ch_req_rx_shift = 24, .ch_base_offset = 0, + .has_outstanding_reqs = false, .ch_fifo_ctrl = TEGRA210_FIFO_CTRL_DEFAULT, .ch_req_mask = 0xf, .ch_req_max = 10, @@ -792,6 +798,7 @@ static const struct tegra_adma_chip_data tegra186_chip_data = { .ch_req_tx_shift = 27, .ch_req_rx_shift = 22, .ch_base_offset = 0x10000, + .has_outstanding_reqs = true, .ch_fifo_ctrl = TEGRA186_FIFO_CTRL_DEFAULT, .ch_req_mask = 0x1f, .ch_req_max = 20, diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c index 2f946f55076c549847fbd0fb1044af3e6f8ed277..8c2f7ebe998c0ba1ec290fa6b6ac4083424daf88 100644 --- a/drivers/dma/ti/cppi41.c +++ b/drivers/dma/ti/cppi41.c @@ -586,9 +586,22 @@ static struct dma_async_tx_descriptor *cppi41_dma_prep_slave_sg( enum dma_transfer_direction dir, unsigned long tx_flags, void *context) { struct cppi41_channel *c = to_cpp41_chan(chan); + struct dma_async_tx_descriptor *txd = NULL; + struct cppi41_dd *cdd = c->cdd; struct cppi41_desc *d; struct scatterlist *sg; unsigned int i; + int error; + + error = pm_runtime_get(cdd->ddev.dev); + if (error < 0) { + pm_runtime_put_noidle(cdd->ddev.dev); + + return NULL; + } + + if (cdd->is_suspended) + goto err_out_not_ready; d = c->desc; for_each_sg(sgl, sg, sg_len, i) { @@ -611,7 +624,13 @@ static struct dma_async_tx_descriptor *cppi41_dma_prep_slave_sg( d++; } - return &c->txd; + txd = &c->txd; + +err_out_not_ready: + pm_runtime_mark_last_busy(cdd->ddev.dev); + pm_runtime_put_autosuspend(cdd->ddev.dev); + + return txd; } static void cppi41_compute_td_desc(struct cppi41_desc *d) diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index e7dc3c4dc8e077d855410055539a2b88a16d9bfb..5d56f1e4d332ce5386b97efb0ec8063b1c659316 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -68,6 +68,9 @@ #define XILINX_DMA_DMACR_CIRC_EN BIT(1) #define XILINX_DMA_DMACR_RUNSTOP BIT(0) #define XILINX_DMA_DMACR_FSYNCSRC_MASK GENMASK(6, 5) +#define XILINX_DMA_DMACR_DELAY_MASK GENMASK(31, 24) +#define XILINX_DMA_DMACR_FRAME_COUNT_MASK GENMASK(23, 16) +#define XILINX_DMA_DMACR_MASTER_MASK GENMASK(11, 8) #define XILINX_DMA_REG_DMASR 0x0004 #define XILINX_DMA_DMASR_EOL_LATE_ERR BIT(15) @@ -1354,7 +1357,8 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) node); hw = &segment->hw; - xilinx_write(chan, XILINX_DMA_REG_SRCDSTADDR, hw->buf_addr); + xilinx_write(chan, XILINX_DMA_REG_SRCDSTADDR, + xilinx_prep_dma_addr_t(hw->buf_addr)); /* Start the transfer */ dma_ctrl_write(chan, XILINX_DMA_REG_BTT, @@ -2117,8 +2121,10 @@ int xilinx_vdma_channel_set_config(struct dma_chan *dchan, chan->config.gen_lock = cfg->gen_lock; chan->config.master = cfg->master; + dmacr &= ~XILINX_DMA_DMACR_GENLOCK_EN; if (cfg->gen_lock && chan->genlock) { dmacr |= XILINX_DMA_DMACR_GENLOCK_EN; + dmacr &= ~XILINX_DMA_DMACR_MASTER_MASK; dmacr |= cfg->master << XILINX_DMA_DMACR_MASTER_SHIFT; } @@ -2134,11 +2140,13 @@ int xilinx_vdma_channel_set_config(struct dma_chan *dchan, chan->config.delay = cfg->delay; if (cfg->coalesc <= XILINX_DMA_DMACR_FRAME_COUNT_MAX) { + dmacr &= ~XILINX_DMA_DMACR_FRAME_COUNT_MASK; dmacr |= cfg->coalesc << XILINX_DMA_DMACR_FRAME_COUNT_SHIFT; chan->config.coalesc = cfg->coalesc; } if (cfg->delay <= XILINX_DMA_DMACR_DELAY_MAX) { + dmacr &= ~XILINX_DMA_DMACR_DELAY_MASK; dmacr |= cfg->delay << XILINX_DMA_DMACR_DELAY_SHIFT; chan->config.delay = cfg->delay; } diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index d413a0bdc9ad9da8637b811e79a81023c39c1906..0bb62857ffb2414cb0b2da26c3591b5c7fb10cbe 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c @@ -553,7 +553,11 @@ void ghes_edac_unregister(struct ghes *ghes) if (!ghes_pvt) return; + if (atomic_dec_return(&ghes_init)) + return; + mci = ghes_pvt->mci; + ghes_pvt = NULL; edac_mc_del_mc(mci->pdev); edac_mc_free(mci); } diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 35ed56b9c34f141a3cdd33c42853bdfc35f13931..1e21fc3e9851a4e6a322173ebffcc2ad1561c9c6 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -408,7 +408,7 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v) bytes = ~0ull; else if (size & 0x8000) bytes = (u64)(size & 0x7fff) << 10; - else if (size != 0x7fff) + else if (size != 0x7fff || dm->length < 0x20) bytes = (u64)size << 20; else bytes = (u64)get_unaligned((u32 *)&d[0x1C]) << 20; diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 178ee8106828775f90a317bbb86a3b75d8dfb9ac..b248870a980611034e616ce403f19e5cca995c86 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -182,6 +182,7 @@ config RESET_ATTACK_MITIGATION config EFI_RCI2_TABLE bool "EFI Runtime Configuration Interface Table Version 2 Support" + depends on X86 || COMPILE_TEST help Displays the content of the Runtime Configuration Interface Table version 2 on Dell EMC PowerEdge systems as a binary diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 69f00f7453a34c386237f4b2344f66a05f3c67fc..e98bbf8e56d9b07e7c609fb614e2105decd99175 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -554,7 +554,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, sizeof(*seed) + size); if (seed != NULL) { pr_notice("seeding entropy pool\n"); - add_device_randomness(seed->bits, seed->size); + add_bootloader_randomness(seed->bits, seed->size); early_memunmap(seed, sizeof(*seed) + size); } else { pr_err("Could not map UEFI random seed!\n"); diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 0460c7581220e13cc8418488042d9a7bb17c0b3e..ee0661ddb25bb6a9e74f52e5c2cced5e85f632c7 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -52,6 +52,7 @@ lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \ lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.o +CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) # diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c index e8f7aefb6813d9c25b85ae367c01aa935a0fe8d1..41213bf5fcf5e8a84619923757fd033cce66761b 100644 --- a/drivers/firmware/efi/libstub/arm32-stub.c +++ b/drivers/firmware/efi/libstub/arm32-stub.c @@ -195,6 +195,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, unsigned long dram_base, efi_loaded_image_t *image) { + unsigned long kernel_base; efi_status_t status; /* @@ -204,9 +205,18 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, * loaded. These assumptions are made by the decompressor, * before any memory map is available. */ - dram_base = round_up(dram_base, SZ_128M); + kernel_base = round_up(dram_base, SZ_128M); - status = reserve_kernel_base(sys_table, dram_base, reserve_addr, + /* + * Note that some platforms (notably, the Raspberry Pi 2) put + * spin-tables and other pieces of firmware at the base of RAM, + * abusing the fact that the window of TEXT_OFFSET bytes at the + * base of the kernel image is only partially used at the moment. + * (Up to 5 pages are used for the swapper page tables) + */ + kernel_base += TEXT_OFFSET - 5 * PAGE_SIZE; + + status = reserve_kernel_base(sys_table, kernel_base, reserve_addr, reserve_size); if (status != EFI_SUCCESS) { pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); @@ -220,7 +230,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, *image_size = image->image_size; status = efi_relocate_kernel(sys_table, image_addr, *image_size, *image_size, - dram_base + MAX_UNCOMP_KERNEL_SIZE, 0); + kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0); if (status != EFI_SUCCESS) { pr_efi_err(sys_table, "Failed to relocate kernel.\n"); efi_free(sys_table, *reserve_size, *reserve_addr); diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 3caae7f2cf56772936b6f77484ef1f7e1a2b42c2..35dbc2791c973f6281470bce96016f1ce37e95a9 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -260,11 +260,11 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, } /* - * Allocate at the lowest possible address. + * Allocate at the lowest possible address that is not below 'min'. */ -efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, - unsigned long size, unsigned long align, - unsigned long *addr) +efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg, + unsigned long size, unsigned long align, + unsigned long *addr, unsigned long min) { unsigned long map_size, desc_size, buff_size; efi_memory_desc_t *map; @@ -311,13 +311,8 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, start = desc->phys_addr; end = start + desc->num_pages * EFI_PAGE_SIZE; - /* - * Don't allocate at 0x0. It will confuse code that - * checks pointers against NULL. Skip the first 8 - * bytes so we start at a nice even number. - */ - if (start == 0x0) - start += 8; + if (start < min) + start = min; start = round_up(start, align); if ((start + size) > end) @@ -698,7 +693,8 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, unsigned long image_size, unsigned long alloc_size, unsigned long preferred_addr, - unsigned long alignment) + unsigned long alignment, + unsigned long min_addr) { unsigned long cur_image_addr; unsigned long new_addr = 0; @@ -731,8 +727,8 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, * possible. */ if (status != EFI_SUCCESS) { - status = efi_low_alloc(sys_table_arg, alloc_size, alignment, - &new_addr); + status = efi_low_alloc_above(sys_table_arg, alloc_size, + alignment, &new_addr, min_addr); } if (status != EFI_SUCCESS) { pr_efi_err(sys_table_arg, "Failed to allocate usable memory for kernel.\n"); diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index 877745c3aaf2833fed62659aa38c52c0f3b2eb1c..7baf48c01e72f2f63e65e802609059da9cdb12ee 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -717,6 +718,13 @@ static long efi_test_ioctl(struct file *file, unsigned int cmd, static int efi_test_open(struct inode *inode, struct file *file) { + int ret = security_locked_down(LOCKDOWN_EFI_TEST); + + if (ret) + return ret; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; /* * nothing special to do here * We do accept multiple open files at the same time as we diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c index ebd7977653a8e28b4a7086573c0e3c80d2e271e3..31f9f0e369b977345dee40523d2f615aec402e84 100644 --- a/drivers/firmware/efi/tpm.c +++ b/drivers/firmware/efi/tpm.c @@ -88,6 +88,7 @@ int __init efi_tpm_eventlog_init(void) if (tbl_size < 0) { pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n"); + ret = -EINVAL; goto out_calc; } diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 4d835f9089df8b95892270b7756604202123e21e..86a10c808ef658c84a1218ccbd7b11e3712197fb 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -293,8 +293,9 @@ static void intel_mid_irq_handler(struct irq_desc *desc) chip->irq_eoi(data); } -static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv) +static int intel_mid_irq_init_hw(struct gpio_chip *chip) { + struct intel_mid_gpio *priv = gpiochip_get_data(chip); void __iomem *reg; unsigned base; @@ -309,6 +310,8 @@ static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv) reg = gpio_reg(&priv->chip, base, GEDR); writel(~0, reg); } + + return 0; } static int __maybe_unused intel_gpio_runtime_idle(struct device *dev) @@ -372,6 +375,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, girq = &priv->chip.irq; girq->chip = &intel_mid_irqchip; + girq->init_hw = intel_mid_irq_init_hw; girq->parent_handler = intel_mid_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, @@ -384,9 +388,8 @@ static int intel_gpio_probe(struct pci_dev *pdev, girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_simple_irq; - intel_mid_irq_init_hw(priv); - pci_set_drvdata(pdev, priv); + retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); if (retval) { dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 6bb9741ad036affb084a47937dfaa73a5f691b37..e9e47c0d5be75ce45671020028784f7a323f8910 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -294,8 +294,9 @@ static struct irq_chip lp_irqchip = { .flags = IRQCHIP_SKIP_SET_WAKE, }; -static void lp_gpio_irq_init_hw(struct lp_gpio *lg) +static int lp_gpio_irq_init_hw(struct gpio_chip *chip) { + struct lp_gpio *lg = gpiochip_get_data(chip); unsigned long reg; unsigned base; @@ -307,6 +308,8 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg) reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); outl(0xffffffff, reg); } + + return 0; } static int lp_gpio_probe(struct platform_device *pdev) @@ -364,6 +367,7 @@ static int lp_gpio_probe(struct platform_device *pdev) girq = &gc->irq; girq->chip = &lp_irqchip; + girq->init_hw = lp_gpio_irq_init_hw; girq->parent_handler = lp_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, @@ -373,9 +377,7 @@ static int lp_gpio_probe(struct platform_device *pdev) return -ENOMEM; girq->parents[0] = (unsigned)irq_rc->start; girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_simple_irq; - - lp_gpio_irq_init_hw(lg); + girq->handler = handle_bad_irq; } ret = devm_gpiochip_add_data(dev, gc, lg); diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 4f27ddfe1e2f07363cec6ab7d20d65f819be61f1..2f1e9da81c1e422644e1611fd5c43b6a14cc0b85 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -362,8 +362,9 @@ static void mrfld_irq_handler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } -static void mrfld_irq_init_hw(struct mrfld_gpio *priv) +static int mrfld_irq_init_hw(struct gpio_chip *chip) { + struct mrfld_gpio *priv = gpiochip_get_data(chip); void __iomem *reg; unsigned int base; @@ -375,6 +376,8 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv) reg = gpio_reg(&priv->chip, base, GFER); writel(0, reg); } + + return 0; } static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv) @@ -447,6 +450,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id girq = &priv->chip.irq; girq->chip = &mrfld_irqchip; + girq->init_hw = mrfld_irq_init_hw; girq->parent_handler = mrfld_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, @@ -455,11 +459,10 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id if (!girq->parents) return -ENOMEM; girq->parents[0] = pdev->irq; + girq->first = irq_base; girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_bad_irq; - mrfld_irq_init_hw(priv); - pci_set_drvdata(pdev, priv); retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); if (retval) { diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5833e4f380d60fe4f585debfd4b47c537bfb7b63..104ed299d5eaa41c439e61dbcde5eb70d620840c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -86,6 +86,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, struct lock_class_key *lock_key, struct lock_class_key *request_key); static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); +static int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip); static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip); static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip); @@ -1406,6 +1407,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, machine_gpiochip_add(chip); + ret = gpiochip_irqchip_init_hw(chip); + if (ret) + goto err_remove_acpi_chip; + ret = gpiochip_irqchip_init_valid_mask(chip); if (ret) goto err_remove_acpi_chip; @@ -1622,6 +1627,16 @@ static struct gpio_chip *find_chip_by_name(const char *name) * The following is irqchip helper code for gpiochips. */ +static int gpiochip_irqchip_init_hw(struct gpio_chip *gc) +{ + struct gpio_irq_chip *girq = &gc->irq; + + if (!girq->init_hw) + return 0; + + return girq->init_hw(gc); +} + static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc) { struct gpio_irq_chip *girq = &gc->irq; @@ -2446,8 +2461,13 @@ static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip, { return 0; } - static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} + +static inline int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip) +{ + return 0; +} + static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) { return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 61e38e43ad1d524f811ad2d7dfaf155a16d97f89..85b0515c0fdcf7c0e69558988fdbb534c9efa302 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -140,7 +140,12 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, return 0; error_free: - while (i--) { + for (i = 0; i < last_entry; ++i) { + struct amdgpu_bo *bo = ttm_to_amdgpu_bo(array[i].tv.bo); + + amdgpu_bo_unref(&bo); + } + for (i = first_userptr; i < num_entries; ++i) { struct amdgpu_bo *bo = ttm_to_amdgpu_bo(array[i].tv.bo); amdgpu_bo_unref(&bo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 2e53feed40e230f7d7f0733678932ef07873db0f..82823d9a8ba8874e33959ef389465210a91f46f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -536,7 +536,6 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, list_for_each_entry(lobj, validated, tv.head) { struct amdgpu_bo *bo = ttm_to_amdgpu_bo(lobj->tv.bo); - bool binding_userptr = false; struct mm_struct *usermm; usermm = amdgpu_ttm_tt_get_usermm(bo->tbo.ttm); @@ -553,7 +552,6 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, amdgpu_ttm_tt_set_user_pages(bo->tbo.ttm, lobj->user_pages); - binding_userptr = true; } if (p->evictable == lobj) @@ -563,10 +561,8 @@ static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p, if (r) return r; - if (binding_userptr) { - kvfree(lobj->user_pages); - lobj->user_pages = NULL; - } + kvfree(lobj->user_pages); + lobj->user_pages = NULL; } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6f8aaf655a9fc36e3ee3022f1c9c861091eb0425..2a00a36106b2d6c78cd6536d2d79ae7933dc4bdc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1048,6 +1048,41 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, return -ENODEV; } +#ifdef CONFIG_DRM_AMDGPU_SI + if (!amdgpu_si_support) { + switch (flags & AMD_ASIC_MASK) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: + case CHIP_HAINAN: + dev_info(&pdev->dev, + "SI support provided by radeon.\n"); + dev_info(&pdev->dev, + "Use radeon.si_support=0 amdgpu.si_support=1 to override.\n" + ); + return -ENODEV; + } + } +#endif +#ifdef CONFIG_DRM_AMDGPU_CIK + if (!amdgpu_cik_support) { + switch (flags & AMD_ASIC_MASK) { + case CHIP_KAVERI: + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_KABINI: + case CHIP_MULLINS: + dev_info(&pdev->dev, + "CIK support provided by radeon.\n"); + dev_info(&pdev->dev, + "Use radeon.cik_support=0 amdgpu.cik_support=1 to override.\n" + ); + return -ENODEV; + } + } +#endif + /* Get rid of things like offb */ ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "amdgpudrmfb"); if (ret) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 9d76e0923a5a3a4d705a0905b63036344b3f3bd7..96b2a31ccfed357956cd347bc0c1b0723d4e9c53 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -218,7 +218,7 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) struct amdgpu_ring *ring = to_amdgpu_ring(sched_job->sched); struct dma_fence *fence = NULL, *finished; struct amdgpu_job *job; - int r; + int r = 0; job = to_amdgpu_job(sched_job); finished = &job->base.s_fence->finished; @@ -243,6 +243,8 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) job->fence = dma_fence_get(fence); amdgpu_job_free_resources(job); + + fence = r ? ERR_PTR(r) : fence; return fence; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index f2c097983f48fb6c760c4fc5b55ba073d487ad88..d55f5baa83d37343edad07b6946f35fb04c698ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -144,41 +144,6 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) struct amdgpu_device *adev; int r, acpi_status; -#ifdef CONFIG_DRM_AMDGPU_SI - if (!amdgpu_si_support) { - switch (flags & AMD_ASIC_MASK) { - case CHIP_TAHITI: - case CHIP_PITCAIRN: - case CHIP_VERDE: - case CHIP_OLAND: - case CHIP_HAINAN: - dev_info(dev->dev, - "SI support provided by radeon.\n"); - dev_info(dev->dev, - "Use radeon.si_support=0 amdgpu.si_support=1 to override.\n" - ); - return -ENODEV; - } - } -#endif -#ifdef CONFIG_DRM_AMDGPU_CIK - if (!amdgpu_cik_support) { - switch (flags & AMD_ASIC_MASK) { - case CHIP_KAVERI: - case CHIP_BONAIRE: - case CHIP_HAWAII: - case CHIP_KABINI: - case CHIP_MULLINS: - dev_info(dev->dev, - "CIK support provided by radeon.\n"); - dev_info(dev->dev, - "Use radeon.cik_support=0 amdgpu.cik_support=1 to override.\n" - ); - return -ENODEV; - } - } -#endif - adev = kzalloc(sizeof(struct amdgpu_device), GFP_KERNEL); if (adev == NULL) { return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 1fead0e8b8909d28e8fe5b2d5bfe6a59634c6b55..7289e1b4fb600e6728765167327c13e193a1b18a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -453,7 +453,8 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, .interruptible = (bp->type != ttm_bo_type_kernel), .no_wait_gpu = false, .resv = bp->resv, - .flags = TTM_OPT_FLAG_ALLOW_RES_EVICT + .flags = bp->type != ttm_bo_type_kernel ? + TTM_OPT_FLAG_ALLOW_RES_EVICT : 0 }; struct amdgpu_bo *bo; unsigned long page_align, size = bp->size; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index b70b3c45bb294f142998aca526e8dcd55920cf15..65044b1b3d4cc2ffce7b5cec9614bd688792a642 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -429,13 +429,14 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp) * Open up a stream for HW test */ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, + struct amdgpu_bo *bo, struct dma_fence **fence) { const unsigned ib_size_dw = 1024; struct amdgpu_job *job; struct amdgpu_ib *ib; struct dma_fence *f = NULL; - uint64_t dummy; + uint64_t addr; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -444,7 +445,7 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, ib = &job->ibs[0]; - dummy = ib->gpu_addr + 1024; + addr = amdgpu_bo_gpu_offset(bo); /* stitch together an VCE create msg */ ib->length_dw = 0; @@ -476,8 +477,8 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, ib->ptr[ib->length_dw++] = 0x00000014; /* len */ ib->ptr[ib->length_dw++] = 0x05000005; /* feedback buffer */ - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); - ib->ptr[ib->length_dw++] = dummy; + ib->ptr[ib->length_dw++] = upper_32_bits(addr); + ib->ptr[ib->length_dw++] = addr; ib->ptr[ib->length_dw++] = 0x00000001; for (i = ib->length_dw; i < ib_size_dw; ++i) @@ -1110,13 +1111,20 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring) int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; + struct amdgpu_bo *bo = NULL; long r; /* skip vce ring1/2 ib test for now, since it's not reliable */ if (ring != &ring->adev->vce.ring[0]) return 0; - r = amdgpu_vce_get_create_msg(ring, 1, NULL); + r = amdgpu_bo_create_reserved(ring->adev, 512, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &bo, NULL, NULL); + if (r) + return r; + + r = amdgpu_vce_get_create_msg(ring, 1, bo, NULL); if (r) goto error; @@ -1132,5 +1140,7 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) error: dma_fence_put(fence); + amdgpu_bo_unreserve(bo); + amdgpu_bo_unref(&bo); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h index 30ea54dd91173b57dbf48e9a9d12915f752d0e13..e802f7d9db0a428de7f8192decad0de4cf10b724 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h @@ -59,6 +59,7 @@ int amdgpu_vce_entity_init(struct amdgpu_device *adev); int amdgpu_vce_suspend(struct amdgpu_device *adev); int amdgpu_vce_resume(struct amdgpu_device *adev); int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, + struct amdgpu_bo *bo, struct dma_fence **fence); int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, bool direct, struct dma_fence **fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 7a6beb2e7c4e8aede558f98f9a3b37aff0affc7a..3199e4a5ff126a86156df7d4b94cdd1a53795bdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -569,13 +569,14 @@ int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring) } static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct dma_fence **fence) + struct amdgpu_bo *bo, + struct dma_fence **fence) { const unsigned ib_size_dw = 16; struct amdgpu_job *job; struct amdgpu_ib *ib; struct dma_fence *f = NULL; - uint64_t dummy; + uint64_t addr; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -583,14 +584,14 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand return r; ib = &job->ibs[0]; - dummy = ib->gpu_addr + 1024; + addr = amdgpu_bo_gpu_offset(bo); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; ib->ptr[ib->length_dw++] = 0x00000001; /* session info */ ib->ptr[ib->length_dw++] = handle; - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); - ib->ptr[ib->length_dw++] = dummy; + ib->ptr[ib->length_dw++] = upper_32_bits(addr); + ib->ptr[ib->length_dw++] = addr; ib->ptr[ib->length_dw++] = 0x0000000b; ib->ptr[ib->length_dw++] = 0x00000014; @@ -621,13 +622,14 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand } static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - struct dma_fence **fence) + struct amdgpu_bo *bo, + struct dma_fence **fence) { const unsigned ib_size_dw = 16; struct amdgpu_job *job; struct amdgpu_ib *ib; struct dma_fence *f = NULL; - uint64_t dummy; + uint64_t addr; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -635,14 +637,14 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han return r; ib = &job->ibs[0]; - dummy = ib->gpu_addr + 1024; + addr = amdgpu_bo_gpu_offset(bo); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; ib->ptr[ib->length_dw++] = 0x00000001; ib->ptr[ib->length_dw++] = handle; - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); - ib->ptr[ib->length_dw++] = dummy; + ib->ptr[ib->length_dw++] = upper_32_bits(addr); + ib->ptr[ib->length_dw++] = addr; ib->ptr[ib->length_dw++] = 0x0000000b; ib->ptr[ib->length_dw++] = 0x00000014; @@ -675,13 +677,20 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; + struct amdgpu_bo *bo = NULL; long r; - r = amdgpu_vcn_enc_get_create_msg(ring, 1, NULL); + r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &bo, NULL, NULL); + if (r) + return r; + + r = amdgpu_vcn_enc_get_create_msg(ring, 1, bo, NULL); if (r) goto error; - r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, &fence); + r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, bo, &fence); if (r) goto error; @@ -693,6 +702,8 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) error: dma_fence_put(fence); + amdgpu_bo_unreserve(bo); + amdgpu_bo_unref(&bo); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 957811b73672a988fd92d8985fe7f0f27569bf58..8dfc775626a7a080ee68f58f79dc18462db14cc9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -93,7 +93,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_1[] = { SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_CPF_CLK_CTRL, 0xfcff8fff, 0xf8000100), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xc0000000, 0xc0000100), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xcd000000, 0x0d000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SQ_CLK_CTRL, 0x60000ff0, 0x60000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SQG_CLK_CTRL, 0x40000000, 0x40000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_VGT_CLK_CTRL, 0xffff8fff, 0xffff8100), @@ -140,7 +140,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_1[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x003c0014), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_GS_NGG_CLK_CTRL, 0xffff8fff, 0xffff8100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_IA_CLK_CTRL, 0xffff0fff, 0xffff0100), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xc0000000, 0xc0000100), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xcd000000, 0x0d000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SQ_CLK_CTRL, 0xf8ff0fff, 0x60000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SQG_CLK_CTRL, 0x40000ff0, 0x40000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_VGT_CLK_CTRL, 0xffff8fff, 0xffff8100), @@ -179,7 +179,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0x003e001f, 0x003c0014), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_GS_NGG_CLK_CTRL, 0xffff8fff, 0xffff8100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_IA_CLK_CTRL, 0xffff0fff, 0xffff0100), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xff7f0fff, 0xc0000100), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_CLK_CTRL, 0xff7f0fff, 0x0d000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SQ_CLK_CTRL, 0xffffcfff, 0x60000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SQG_CLK_CTRL, 0xffff0fff, 0x40000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_VGT_CLK_CTRL, 0xffff8fff, 0xffff8100), diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 8b789f750b72b0ecba603bb2982cd4e8ada03d60..db10640a3b2f3603fd5b0f84b0d329b28836420e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -151,6 +151,15 @@ static void gfxhub_v2_0_init_cache_regs(struct amdgpu_device *adev) WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL2, tmp); tmp = mmGCVM_L2_CNTL3_DEFAULT; + if (adev->gmc.translate_further) { + tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 12); + tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, + L2_CACHE_BIGK_FRAGMENT_SIZE, 9); + } else { + tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 9); + tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, + L2_CACHE_BIGK_FRAGMENT_SIZE, 6); + } WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL3, tmp); tmp = mmGCVM_L2_CNTL4_DEFAULT; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 241a4e57cf4a993ea1756523c3b69f208f30a9d7..354e6200ca9a129c903399fbebf6848089266bd1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -309,6 +309,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, job->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gart.bo); job->vm_needs_flush = true; + job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop; amdgpu_ring_pad_ib(ring, &job->ibs[0]); r = amdgpu_job_submit(job, &adev->mman.entity, AMDGPU_FENCE_OWNER_UNDEFINED, &fence); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 3542c203c3c8f487a0f4dad537fc5f52cdbdf072..b39bea6f54e97b36060029c17bd36cf6cd00760a 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -137,6 +137,15 @@ static void mmhub_v2_0_init_cache_regs(struct amdgpu_device *adev) WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL2, tmp); tmp = mmMMVM_L2_CNTL3_DEFAULT; + if (adev->gmc.translate_further) { + tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3, BANK_SELECT, 12); + tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3, + L2_CACHE_BIGK_FRAGMENT_SIZE, 9); + } else { + tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3, BANK_SELECT, 9); + tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL3, + L2_CACHE_BIGK_FRAGMENT_SIZE, 6); + } WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL3, tmp); tmp = mmMMVM_L2_CNTL4_DEFAULT; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 78452cf0115df0dc5ad41d93a167c3c83b40db8c..4554e72c83786960ea11eccedd7b89b9372667e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -254,6 +254,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_3[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000) }; static u32 sdma_v4_0_get_reg_offset(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index fa2f70ce2e2b49bfa5a4c1d116b10a78ddeedb79..f6e81680dd7e8edd03cc2ada50008db924d93692 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -1129,7 +1129,7 @@ static void sdma_v5_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, addr & 0xfffffffc); amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff); amdgpu_ring_write(ring, seq); /* reference */ - amdgpu_ring_write(ring, 0xfffffff); /* mask */ + amdgpu_ring_write(ring, 0xffffffff); /* mask */ amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) | SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(4)); /* retry count, poll interval */ } diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 670784a78512b82a7c0f5e484746308ad1fd904d..217084d56ab8c86e6b1b16b335bc4faf13258136 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -206,13 +206,14 @@ static int uvd_v6_0_enc_ring_test_ring(struct amdgpu_ring *ring) * Open up a stream for HW test */ static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, + struct amdgpu_bo *bo, struct dma_fence **fence) { const unsigned ib_size_dw = 16; struct amdgpu_job *job; struct amdgpu_ib *ib; struct dma_fence *f = NULL; - uint64_t dummy; + uint64_t addr; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -220,15 +221,15 @@ static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle return r; ib = &job->ibs[0]; - dummy = ib->gpu_addr + 1024; + addr = amdgpu_bo_gpu_offset(bo); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; ib->ptr[ib->length_dw++] = 0x00000001; /* session info */ ib->ptr[ib->length_dw++] = handle; ib->ptr[ib->length_dw++] = 0x00010000; - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); - ib->ptr[ib->length_dw++] = dummy; + ib->ptr[ib->length_dw++] = upper_32_bits(addr); + ib->ptr[ib->length_dw++] = addr; ib->ptr[ib->length_dw++] = 0x00000014; ib->ptr[ib->length_dw++] = 0x00000002; /* task info */ @@ -268,13 +269,14 @@ static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle */ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, + struct amdgpu_bo *bo, struct dma_fence **fence) { const unsigned ib_size_dw = 16; struct amdgpu_job *job; struct amdgpu_ib *ib; struct dma_fence *f = NULL; - uint64_t dummy; + uint64_t addr; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -282,15 +284,15 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring, return r; ib = &job->ibs[0]; - dummy = ib->gpu_addr + 1024; + addr = amdgpu_bo_gpu_offset(bo); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; ib->ptr[ib->length_dw++] = 0x00000001; /* session info */ ib->ptr[ib->length_dw++] = handle; ib->ptr[ib->length_dw++] = 0x00010000; - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); - ib->ptr[ib->length_dw++] = dummy; + ib->ptr[ib->length_dw++] = upper_32_bits(addr); + ib->ptr[ib->length_dw++] = addr; ib->ptr[ib->length_dw++] = 0x00000014; ib->ptr[ib->length_dw++] = 0x00000002; /* task info */ @@ -327,13 +329,20 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring, static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; + struct amdgpu_bo *bo = NULL; long r; - r = uvd_v6_0_enc_get_create_msg(ring, 1, NULL); + r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &bo, NULL, NULL); + if (r) + return r; + + r = uvd_v6_0_enc_get_create_msg(ring, 1, bo, NULL); if (r) goto error; - r = uvd_v6_0_enc_get_destroy_msg(ring, 1, &fence); + r = uvd_v6_0_enc_get_destroy_msg(ring, 1, bo, &fence); if (r) goto error; @@ -345,6 +354,8 @@ static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) error: dma_fence_put(fence); + amdgpu_bo_unreserve(bo); + amdgpu_bo_unref(&bo); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index 01f658fa72c68a904d678fcf9f131dd5f2675924..0995378d8263c495799068bee36b95c00874fe1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -214,13 +214,14 @@ static int uvd_v7_0_enc_ring_test_ring(struct amdgpu_ring *ring) * Open up a stream for HW test */ static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, + struct amdgpu_bo *bo, struct dma_fence **fence) { const unsigned ib_size_dw = 16; struct amdgpu_job *job; struct amdgpu_ib *ib; struct dma_fence *f = NULL; - uint64_t dummy; + uint64_t addr; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -228,15 +229,15 @@ static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle return r; ib = &job->ibs[0]; - dummy = ib->gpu_addr + 1024; + addr = amdgpu_bo_gpu_offset(bo); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; ib->ptr[ib->length_dw++] = 0x00000001; /* session info */ ib->ptr[ib->length_dw++] = handle; ib->ptr[ib->length_dw++] = 0x00000000; - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); - ib->ptr[ib->length_dw++] = dummy; + ib->ptr[ib->length_dw++] = upper_32_bits(addr); + ib->ptr[ib->length_dw++] = addr; ib->ptr[ib->length_dw++] = 0x00000014; ib->ptr[ib->length_dw++] = 0x00000002; /* task info */ @@ -275,13 +276,14 @@ static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle * Close up a stream for HW test or if userspace failed to do so */ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - struct dma_fence **fence) + struct amdgpu_bo *bo, + struct dma_fence **fence) { const unsigned ib_size_dw = 16; struct amdgpu_job *job; struct amdgpu_ib *ib; struct dma_fence *f = NULL; - uint64_t dummy; + uint64_t addr; int i, r; r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); @@ -289,15 +291,15 @@ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handl return r; ib = &job->ibs[0]; - dummy = ib->gpu_addr + 1024; + addr = amdgpu_bo_gpu_offset(bo); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; ib->ptr[ib->length_dw++] = 0x00000001; ib->ptr[ib->length_dw++] = handle; ib->ptr[ib->length_dw++] = 0x00000000; - ib->ptr[ib->length_dw++] = upper_32_bits(dummy); - ib->ptr[ib->length_dw++] = dummy; + ib->ptr[ib->length_dw++] = upper_32_bits(addr); + ib->ptr[ib->length_dw++] = addr; ib->ptr[ib->length_dw++] = 0x00000014; ib->ptr[ib->length_dw++] = 0x00000002; @@ -334,13 +336,20 @@ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handl static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; + struct amdgpu_bo *bo = NULL; long r; - r = uvd_v7_0_enc_get_create_msg(ring, 1, NULL); + r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &bo, NULL, NULL); + if (r) + return r; + + r = uvd_v7_0_enc_get_create_msg(ring, 1, bo, NULL); if (r) goto error; - r = uvd_v7_0_enc_get_destroy_msg(ring, 1, &fence); + r = uvd_v7_0_enc_get_destroy_msg(ring, 1, bo, &fence); if (r) goto error; @@ -352,6 +361,8 @@ static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) error: dma_fence_put(fence); + amdgpu_bo_unreserve(bo); + amdgpu_bo_unref(&bo); return r; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 985633c08a26725a5315557dbadd0f13f3c2fa76..26c6d735cdc78523af4d6186ac05c50cf7845512 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -24,15 +24,20 @@ # It calculates Bandwidth and Watermarks values for HW programming # -ifneq ($(call cc-option, -mpreferred-stack-boundary=4),) - cc_stack_align := -mpreferred-stack-boundary=4 -else ifneq ($(call cc-option, -mstack-alignment=16),) - cc_stack_align := -mstack-alignment=16 -endif +calcs_ccflags := -mhard-float -msse -calcs_ccflags := -mhard-float -msse $(cc_stack_align) +ifdef CONFIG_CC_IS_GCC +ifeq ($(call cc-ifversion, -lt, 0701, y), y) +IS_OLD_GCC = 1 +endif +endif -ifdef CONFIG_CC_IS_CLANG +ifdef IS_OLD_GCC +# Stack alignment mismatch, proceed with caution. +# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +# (8B stack alignment). +calcs_ccflags += -mpreferred-stack-boundary=4 +else calcs_ccflags += -msse2 endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5d1adeda4d90fa189bfa5dc36bea2bdce30cf72a..4b8819c27fcda3a3011e58f2a5de081cd8ccd25d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -580,6 +580,10 @@ static bool construct(struct dc *dc, #ifdef CONFIG_DRM_AMD_DC_DCN2_0 // Allocate memory for the vm_helper dc->vm_helper = kzalloc(sizeof(struct vm_helper), GFP_KERNEL); + if (!dc->vm_helper) { + dm_error("%s: failed to create dc->vm_helper\n", __func__); + goto fail; + } #endif memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides)); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ca20b150afcc237ba21f8ad46f4bc3bb3b1d97d4..9c58670d541402d0f0b5780cfaa22d3dff4346b2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2767,6 +2767,15 @@ void core_link_enable_stream( CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, COLOR_DEPTH_UNDEFINED); + /* This second call is needed to reconfigure the DIG + * as a workaround for the incorrect value being applied + * from transmitter control. + */ + if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) + stream->link->link_enc->funcs->setup( + stream->link->link_enc, + pipe_ctx->stream->signal); + #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT if (pipe_ctx->stream->timing.flags.DSC) { if (dc_is_dp_signal(pipe_ctx->stream->signal) || diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 505967b48e144b7701dc0c70f92299636c6965ad..51991bf26a93cb9ee1484d5a45856331d242c2c4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -374,6 +374,7 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( enum display_dongle_type *dongle = &sink_cap->dongle_type; uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE]; bool is_type2_dongle = false; + int retry_count = 2; struct dp_hdmi_dongle_signature_data *dongle_signature; /* Assume we have no valid DP passive dongle connected */ @@ -386,13 +387,24 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( DP_HDMI_DONGLE_ADDRESS, type2_dongle_buf, sizeof(type2_dongle_buf))) { - *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; - sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; + /* Passive HDMI dongles can sometimes fail here without retrying*/ + while (retry_count > 0) { + if (i2c_read(ddc, + DP_HDMI_DONGLE_ADDRESS, + type2_dongle_buf, + sizeof(type2_dongle_buf))) + break; + retry_count--; + } + if (retry_count == 0) { + *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; + sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; - CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf), - "DP-DVI passive dongle %dMhz: ", - DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000); - return; + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf), + "DP-DVI passive dongle %dMhz: ", + DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000); + return; + } } /* Check if Type 2 dongle.*/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8f70295179ffa2aad20982f28d79da8661ff0496..f25ac17f47fa9f7da19512a19db07297ce91a660 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -404,6 +404,9 @@ bool resource_are_streams_timing_synchronizable( if (stream1->view_format != stream2->view_format) return false; + if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) + return false; + return true; } static bool is_dp_and_hdmi_sharable( @@ -1540,6 +1543,9 @@ bool dc_is_stream_unchanged( if (!are_stream_backends_same(old_stream, stream)) return false; + if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) + return false; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index 01c7e30b9ce1786d0f333213e511ee9d45572fff..bbd6e01b3eca41df79079ce78bf426c6ee31c41b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -393,6 +393,10 @@ bool cm_helper_translate_curve_to_hw_format( rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; + rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red; + rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green; + rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue; + // All 3 color channels have same x corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), dc_fixpt_from_int(region_start)); @@ -464,13 +468,6 @@ bool cm_helper_translate_curve_to_hw_format( i = 1; while (i != hw_points + 1) { - if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) - rgb_plus_1->red = rgb->red; - if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) - rgb_plus_1->green = rgb->green; - if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) - rgb_plus_1->blue = rgb->blue; - rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); @@ -562,6 +559,10 @@ bool cm_helper_translate_curve_to_degamma_hw_format( rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; + rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red; + rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green; + rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue; + corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), dc_fixpt_from_int(region_start)); corner_points[0].green.x = corner_points[0].red.x; @@ -624,13 +625,6 @@ bool cm_helper_translate_curve_to_degamma_hw_format( i = 1; while (i != hw_points + 1) { - if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) - rgb_plus_1->red = rgb->red; - if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) - rgb_plus_1->green = rgb->green; - if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) - rgb_plus_1->blue = rgb->blue; - rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index ddb8d5649e79184f901161668c91fa3098416406..63f3bddba7daaa50ab93dbd9a42fc13327208d84 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -10,15 +10,20 @@ ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT DCN20 += dcn20_dsc.o endif -ifneq ($(call cc-option, -mpreferred-stack-boundary=4),) - cc_stack_align := -mpreferred-stack-boundary=4 -else ifneq ($(call cc-option, -mstack-alignment=16),) - cc_stack_align := -mstack-alignment=16 -endif +CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -msse -CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -msse $(cc_stack_align) +ifdef CONFIG_CC_IS_GCC +ifeq ($(call cc-ifversion, -lt, 0701, y), y) +IS_OLD_GCC = 1 +endif +endif -ifdef CONFIG_CC_IS_CLANG +ifdef IS_OLD_GCC +# Stack alignment mismatch, proceed with caution. +# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +# (8B stack alignment). +CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o += -mpreferred-stack-boundary=4 +else CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o += -msse2 endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 5a2763daff4d65980733292d652ad9770c3615ca..dfb208285a9cdd6cb817afbc3cf0ac3a1964200b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -814,7 +814,7 @@ static const struct resource_caps res_cap_nv14 = { .num_audio = 6, .num_stream_encoder = 5, .num_pll = 5, - .num_dwb = 0, + .num_dwb = 1, .num_ddc = 5, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile index ef673bffc241ef0bff3cafb24a7f05ade7ed6ff1..ff50ae71fe277b0052440a9a67d175c3c2293b6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile @@ -3,15 +3,20 @@ DCN21 = dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o -ifneq ($(call cc-option, -mpreferred-stack-boundary=4),) - cc_stack_align := -mpreferred-stack-boundary=4 -else ifneq ($(call cc-option, -mstack-alignment=16),) - cc_stack_align := -mstack-alignment=16 -endif +CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -msse -CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -msse $(cc_stack_align) +ifdef CONFIG_CC_IS_GCC +ifeq ($(call cc-ifversion, -lt, 0701, y), y) +IS_OLD_GCC = 1 +endif +endif -ifdef CONFIG_CC_IS_CLANG +ifdef IS_OLD_GCC +# Stack alignment mismatch, proceed with caution. +# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +# (8B stack alignment). +CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o += -mpreferred-stack-boundary=4 +else CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o += -msse2 endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 5b2a65b424036e07935122dfb38d0a529097c5d5..8df251626e22bf10fd3e8924bea490850b04b228 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -24,15 +24,20 @@ # It provides the general basic services required by other DAL # subcomponents. -ifneq ($(call cc-option, -mpreferred-stack-boundary=4),) - cc_stack_align := -mpreferred-stack-boundary=4 -else ifneq ($(call cc-option, -mstack-alignment=16),) - cc_stack_align := -mstack-alignment=16 -endif +dml_ccflags := -mhard-float -msse -dml_ccflags := -mhard-float -msse $(cc_stack_align) +ifdef CONFIG_CC_IS_GCC +ifeq ($(call cc-ifversion, -lt, 0701, y), y) +IS_OLD_GCC = 1 +endif +endif -ifdef CONFIG_CC_IS_CLANG +ifdef IS_OLD_GCC +# Stack alignment mismatch, proceed with caution. +# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +# (8B stack alignment). +dml_ccflags += -mpreferred-stack-boundary=4 +else dml_ccflags += -msse2 endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c index 649883777f62a6ff9e08c7154ea8204138f05afa..6c6c486b774a4ea8d043ba8cae61a4ac6a36cbd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c @@ -2577,7 +2577,8 @@ static void dml20_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPer mode_lib->vba.MinActiveDRAMClockChangeMargin + mode_lib->vba.DRAMClockChangeLatency; - if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { + if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 50) { + mode_lib->vba.DRAMClockChangeWatermark += 25; mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; } else { if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile index b456cd23c6fa46e48b7a5b40f9d76074e57b4396..970737217e53a18ee4331e3cc3aa570c63a79780 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile @@ -1,15 +1,20 @@ # # Makefile for the 'dsc' sub-component of DAL. -ifneq ($(call cc-option, -mpreferred-stack-boundary=4),) - cc_stack_align := -mpreferred-stack-boundary=4 -else ifneq ($(call cc-option, -mstack-alignment=16),) - cc_stack_align := -mstack-alignment=16 -endif +dsc_ccflags := -mhard-float -msse -dsc_ccflags := -mhard-float -msse $(cc_stack_align) +ifdef CONFIG_CC_IS_GCC +ifeq ($(call cc-ifversion, -lt, 0701, y), y) +IS_OLD_GCC = 1 +endif +endif -ifdef CONFIG_CC_IS_CLANG +ifdef IS_OLD_GCC +# Stack alignment mismatch, proceed with caution. +# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +# (8B stack alignment). +dsc_ccflags += -mpreferred-stack-boundary=4 +else dsc_ccflags += -msse2 endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index d08493b67b67d1d2d67985777ea7003c29593fb6..beacfffbdc3eba36468ca5164540e419473fbd48 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -5098,9 +5098,7 @@ static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr, if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; - for (i = 0; i < podn_vdd_dep->count - 1; i++) - od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc; - if (od_vddc_lookup_table->entries[i].us_vdd < podn_vdd_dep->entries[i].vddc) + for (i = 0; i < podn_vdd_dep->count; i++) od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc; } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index dc754447f0ddc7a84592ccdfb19e3bddc561061d..23c12018dbc18c582a99610d8575d6555861c7f7 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -655,7 +655,7 @@ static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, count = SMU_MAX_SMIO_LEVELS; for (level = 0; level < count; level++) { table->SmioTable2.Pattern[level].Voltage = - PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); + PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[level].value * VOLTAGE_SCALE); /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ table->SmioTable2.Pattern[level].Smio = (uint8_t) level; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c index 7c960b07746fd28da3f44920a65092f15c517848..ae18fbcb26fb19ce8ad203c649d22c017717c423 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c @@ -456,7 +456,7 @@ static int vegam_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, count = SMU_MAX_SMIO_LEVELS; for (level = 0; level < count; level++) { table->SmioTable2.Pattern[level].Voltage = PP_HOST_TO_SMC_US( - data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); + data->mvdd_voltage_table.entries[level].value * VOLTAGE_SCALE); /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ table->SmioTable2.Pattern[level].Smio = (uint8_t) level; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 8820ce15ce375df111338db44d59821018cfc51c..ae274902ff92439f048d3d04ef034ef0f29d4b61 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -82,7 +82,8 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) drm_atomic_helper_commit_modeset_disables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state, 0); + drm_atomic_helper_commit_planes(dev, old_state, + DRM_PLANE_COMMIT_ACTIVE_ONLY); drm_atomic_helper_commit_modeset_enables(dev, old_state); diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c index ea26bc9c2d0012e7c4703227464f462b70f1fd4b..b848270e0a1f4323c1a0fd7cc18e11afcd159169 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c @@ -564,8 +564,8 @@ komeda_splitter_validate(struct komeda_splitter *splitter, } if (!in_range(&splitter->vsize, dflow->in_h)) { - DRM_DEBUG_ATOMIC("split in_in: %d exceed the acceptable range.\n", - dflow->in_w); + DRM_DEBUG_ATOMIC("split in_h: %d exceeds the acceptable range.\n", + dflow->in_h); return -EINVAL; } diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 82a4ceed3fcf5a77bbb87b667b7c8375e9a19863..6b0177112e18d97e05514037a9f37f7c13fb7fc9 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -159,6 +159,9 @@ static const struct edid_quirk { /* Medion MD 30217 PG */ { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, + /* Lenovo G50 */ + { "SDC", 18514, EDID_QUIRK_FORCE_6BPC }, + /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */ { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC }, diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index fcd728d7cf72279a820160c28fbfd1ea2fefa54f..e293cf7bc35c906386ad3954b8c2564763c9f31c 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -676,9 +676,9 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0), DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 0), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 0), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, 0), DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER), diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c index 698db540972c3a09ec3f3147bd87eea156681f4a..648cf0207309219362c7d94df777fc00fece30d1 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c @@ -180,6 +180,8 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit) etnaviv_cmdbuf_get_va(&submit->cmdbuf, &gpu->mmu_context->cmdbuf_mapping)); + mutex_unlock(&gpu->mmu_context->lock); + /* Reserve space for the bomap */ if (n_bomap_pages) { bomap_start = bomap = iter.data; @@ -221,8 +223,6 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit) obj->base.size); } - mutex_unlock(&gpu->mmu_context->lock); - etnaviv_core_dump_header(&iter, ETDUMP_BUF_END, iter.data); dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start, GFP_KERNEL); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c index 043111a1d60c4f9712c96abb427bbcfb4816d2e3..f8bf488e9d717360aa21a9f7f3db45ed25dd5278 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c @@ -155,9 +155,11 @@ static void etnaviv_iommuv2_dump(struct etnaviv_iommu_context *context, void *bu memcpy(buf, v2_context->mtlb_cpu, SZ_4K); buf += SZ_4K; - for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++, buf += SZ_4K) - if (v2_context->mtlb_cpu[i] & MMUv2_PTE_PRESENT) + for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) + if (v2_context->mtlb_cpu[i] & MMUv2_PTE_PRESENT) { memcpy(buf, v2_context->stlb_cpu[i], SZ_4K); + buf += SZ_4K; + } } static void etnaviv_iommuv2_restore_nonsec(struct etnaviv_gpu *gpu, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index 35ebae6a1be7ddbbbe9b42d8f16349a082fc155a..3607d348c2980f1332e8a7a02faa80ce6619814c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -328,12 +328,23 @@ etnaviv_iommu_context_init(struct etnaviv_iommu_global *global, ret = etnaviv_cmdbuf_suballoc_map(suballoc, ctx, &ctx->cmdbuf_mapping, global->memory_base); - if (ret) { - global->ops->free(ctx); - return NULL; + if (ret) + goto out_free; + + if (global->version == ETNAVIV_IOMMU_V1 && + ctx->cmdbuf_mapping.iova > 0x80000000) { + dev_err(global->dev, + "command buffer outside valid memory window\n"); + goto out_unmap; } return ctx; + +out_unmap: + etnaviv_cmdbuf_suballoc_unmap(ctx, &ctx->cmdbuf_mapping); +out_free: + global->ops->free(ctx); + return NULL; } void etnaviv_iommu_restore(struct etnaviv_gpu *gpu, diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index efb39f350b19643b5c6d2418a96c08d128d54dee..3250c1b8dccaebe864bd2eecdc8b10a88fa8221a 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1270,7 +1270,7 @@ static void sanitize_ddc_pin(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, " "disabling port %c DVI/HDMI support\n", port_name(port), info->alternate_ddc_pin, - port_name(p), port_name(port)); + port_name(p), port_name(p)); /* * If we have multiple ports supposedly sharing the @@ -1278,9 +1278,14 @@ static void sanitize_ddc_pin(struct drm_i915_private *dev_priv, * port. Otherwise they share the same ddc bin and * system couldn't communicate with them separately. * - * Give child device order the priority, first come first - * served. + * Give inverse child device order the priority, + * last one wins. Yes, there are real machines + * (eg. Asrock B250M-HDV) where VBT has both + * port A and port E with the same AUX ch and + * we must pick port E :( */ + info = &dev_priv->vbt.ddi_port_info[p]; + info->supports_dvi = false; info->supports_hdmi = false; info->alternate_ddc_pin = 0; @@ -1316,7 +1321,7 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, " "disabling port %c DP support\n", port_name(port), info->alternate_aux_channel, - port_name(p), port_name(port)); + port_name(p), port_name(p)); /* * If we have multiple ports supposedlt sharing the @@ -1324,9 +1329,14 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv, * port. Otherwise they share the same aux channel * and system couldn't communicate with them separately. * - * Give child device order the priority, first come first - * served. + * Give inverse child device order the priority, + * last one wins. Yes, there are real machines + * (eg. Asrock B250M-HDV) where VBT has both + * port A and port E with the same AUX ch and + * we must pick port E :( */ + info = &dev_priv->vbt.ddi_port_info[p]; + info->supports_dp = false; info->alternate_aux_channel = 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index aa54bb22796da72405f27854497d3cc3f638218b..dfff6f4357b85a7307db60298d3f5b441011fe94 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -9315,7 +9315,6 @@ static bool wrpll_uses_pch_ssc(struct drm_i915_private *dev_priv, static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) { struct intel_encoder *encoder; - bool pch_ssc_in_use = false; bool has_fdi = false; for_each_intel_encoder(&dev_priv->drm, encoder) { @@ -9343,22 +9342,24 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) * clock hierarchy. That would also allow us to do * clock bending finally. */ + dev_priv->pch_ssc_use = 0; + if (spll_uses_pch_ssc(dev_priv)) { DRM_DEBUG_KMS("SPLL using PCH SSC\n"); - pch_ssc_in_use = true; + dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) { DRM_DEBUG_KMS("WRPLL1 using PCH SSC\n"); - pch_ssc_in_use = true; + dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) { DRM_DEBUG_KMS("WRPLL2 using PCH SSC\n"); - pch_ssc_in_use = true; + dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2); } - if (pch_ssc_in_use) + if (dev_priv->pch_ssc_use) return; if (has_fdi) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index b8148f838354cecafe94b768d20bf3c553ad868c..d5a298c3c83b19a31cc9f9deb23bc7dfc2a1e224 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -525,16 +525,31 @@ static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, val = I915_READ(WRPLL_CTL(id)); I915_WRITE(WRPLL_CTL(id), val & ~WRPLL_PLL_ENABLE); POSTING_READ(WRPLL_CTL(id)); + + /* + * Try to set up the PCH reference clock once all DPLLs + * that depend on it have been shut down. + */ + if (dev_priv->pch_ssc_use & BIT(id)) + intel_init_pch_refclk(dev_priv); } static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { + enum intel_dpll_id id = pll->info->id; u32 val; val = I915_READ(SPLL_CTL); I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); POSTING_READ(SPLL_CTL); + + /* + * Try to set up the PCH reference clock once all DPLLs + * that depend on it have been shut down. + */ + if (dev_priv->pch_ssc_use & BIT(id)) + intel_init_pch_refclk(dev_priv); } static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index e7588799fce565d681a7391b98a37ca3a61e3d78..104cf6d42333e5607139fccc16698db20f20fe0f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -147,11 +147,11 @@ enum intel_dpll_id { */ DPLL_ID_ICL_MGPLL4 = 6, /** - * @DPLL_ID_TGL_TCPLL5: TGL TC PLL port 5 (TC5) + * @DPLL_ID_TGL_MGPLL5: TGL TC PLL port 5 (TC5) */ DPLL_ID_TGL_MGPLL5 = 7, /** - * @DPLL_ID_TGL_TCPLL6: TGL TC PLL port 6 (TC6) + * @DPLL_ID_TGL_MGPLL6: TGL TC PLL port 6 (TC6) */ DPLL_ID_TGL_MGPLL6 = 8, }; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 91051e1780217d8d593b0469fa41b0c61576054a..05289edbafe34b8dbaf1890973f345b0aba5c3e0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -364,6 +364,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf) return VM_FAULT_OOM; case -ENOSPC: case -EFAULT: + case -ENODEV: /* bad object, how did you get here! */ return VM_FAULT_SIGBUS; default: WARN_ONCE(ret, "unhandled error in %s: %i\n", __func__, ret); @@ -475,10 +476,16 @@ i915_gem_mmap_gtt(struct drm_file *file, if (!obj) return -ENOENT; + if (i915_gem_object_never_bind_ggtt(obj)) { + ret = -ENODEV; + goto out; + } + ret = create_mmap_offset(obj); if (ret == 0) *offset = drm_vma_node_offset_addr(&obj->base.vma_node); +out: i915_gem_object_put(obj); return ret; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 5efb9936e05b512fe9d7dbcd47cf8069ac844e2e..ddf3605bea8eb4f3aaeb8a097507a0c9805acb58 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -152,6 +152,12 @@ i915_gem_object_is_proxy(const struct drm_i915_gem_object *obj) return obj->ops->flags & I915_GEM_OBJECT_IS_PROXY; } +static inline bool +i915_gem_object_never_bind_ggtt(const struct drm_i915_gem_object *obj) +{ + return obj->ops->flags & I915_GEM_OBJECT_NO_GGTT; +} + static inline bool i915_gem_object_needs_async_cancel(const struct drm_i915_gem_object *obj) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index ede0eb4218a81b9f1c67390afe7b2433afdf7a49..646859fea2246fad71e79f4ce14f8102759f573d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -32,7 +32,8 @@ struct drm_i915_gem_object_ops { #define I915_GEM_OBJECT_HAS_STRUCT_PAGE BIT(0) #define I915_GEM_OBJECT_IS_SHRINKABLE BIT(1) #define I915_GEM_OBJECT_IS_PROXY BIT(2) -#define I915_GEM_OBJECT_ASYNC_CANCEL BIT(3) +#define I915_GEM_OBJECT_NO_GGTT BIT(3) +#define I915_GEM_OBJECT_ASYNC_CANCEL BIT(4) /* Interface between the GEM object and its backing storage. * get_pages() is called once prior to the use of the associated set diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index 11b231c187c500f104e85bc736a0a1f4b36f2f4a..6b3b50f0f6d98bc856c5e48f41d5d09d3193f2d8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -702,6 +702,7 @@ i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj) static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE | I915_GEM_OBJECT_IS_SHRINKABLE | + I915_GEM_OBJECT_NO_GGTT | I915_GEM_OBJECT_ASYNC_CANCEL, .get_pages = i915_gem_userptr_get_pages, .put_pages = i915_gem_userptr_put_pages, diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index bdfcc7bdadbf49e41d67538625db46a30c7557d1..06a506c29463d67b3b1c23d4834ccc2598fac273 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -234,6 +234,13 @@ static void execlists_init_reg_state(u32 *reg_state, struct intel_engine_cs *engine, struct intel_ring *ring); +static void mark_eio(struct i915_request *rq) +{ + if (!i915_request_signaled(rq)) + dma_fence_set_error(&rq->fence, -EIO); + i915_request_mark_complete(rq); +} + static inline u32 intel_hws_preempt_address(struct intel_engine_cs *engine) { return (i915_ggtt_offset(engine->status_page.vma) + @@ -1236,6 +1243,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) submit = true; last = rq; } + i915_request_put(rq); /* * Hmm, we have a bunch of virtual engine requests, @@ -2574,12 +2582,8 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) __execlists_reset(engine, true); /* Mark all executing requests as skipped. */ - list_for_each_entry(rq, &engine->active.requests, sched.link) { - if (!i915_request_signaled(rq)) - dma_fence_set_error(&rq->fence, -EIO); - - i915_request_mark_complete(rq); - } + list_for_each_entry(rq, &engine->active.requests, sched.link) + mark_eio(rq); /* Flush the queued requests to the timeline list (for retiring). */ while ((rb = rb_first_cached(&execlists->queue))) { @@ -2587,9 +2591,8 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) int i; priolist_for_each_request_consume(rq, rn, p, i) { + mark_eio(rq); __i915_request_submit(rq); - dma_fence_set_error(&rq->fence, -EIO); - i915_request_mark_complete(rq); } rb_erase_cached(&p->node, &execlists->queue); @@ -2605,13 +2608,15 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) RB_CLEAR_NODE(rb); spin_lock(&ve->base.active.lock); - if (ve->request) { - ve->request->engine = engine; - __i915_request_submit(ve->request); - dma_fence_set_error(&ve->request->fence, -EIO); - i915_request_mark_complete(ve->request); + rq = fetch_and_zero(&ve->request); + if (rq) { + mark_eio(rq); + + rq->engine = engine; + __i915_request_submit(rq); + i915_request_put(rq); + ve->base.execlists.queue_priority_hint = INT_MIN; - ve->request = NULL; } spin_unlock(&ve->base.active.lock); } @@ -3615,6 +3620,8 @@ static void virtual_submission_tasklet(unsigned long data) static void virtual_submit_request(struct i915_request *rq) { struct virtual_engine *ve = to_virtual_engine(rq->engine); + struct i915_request *old; + unsigned long flags; GEM_TRACE("%s: rq=%llx:%lld\n", ve->base.name, @@ -3623,15 +3630,31 @@ static void virtual_submit_request(struct i915_request *rq) GEM_BUG_ON(ve->base.submit_request != virtual_submit_request); - GEM_BUG_ON(ve->request); - GEM_BUG_ON(!list_empty(virtual_queue(ve))); + spin_lock_irqsave(&ve->base.active.lock, flags); + + old = ve->request; + if (old) { /* background completion event from preempt-to-busy */ + GEM_BUG_ON(!i915_request_completed(old)); + __i915_request_submit(old); + i915_request_put(old); + } - ve->base.execlists.queue_priority_hint = rq_prio(rq); - WRITE_ONCE(ve->request, rq); + if (i915_request_completed(rq)) { + __i915_request_submit(rq); - list_move_tail(&rq->sched.link, virtual_queue(ve)); + ve->base.execlists.queue_priority_hint = INT_MIN; + ve->request = NULL; + } else { + ve->base.execlists.queue_priority_hint = rq_prio(rq); + ve->request = i915_request_get(rq); + + GEM_BUG_ON(!list_empty(virtual_queue(ve))); + list_move_tail(&rq->sched.link, virtual_queue(ve)); + + tasklet_schedule(&ve->base.execlists.tasklet); + } - tasklet_schedule(&ve->base.execlists.tasklet); + spin_unlock_irqrestore(&ve->base.active.lock, flags); } static struct ve_bond * diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 772154e4073e267bf4368a97c301f6602f75c0d8..953e1d12c23ce2e5fe1a2ee7da8a6fa9e015aa0a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1723,6 +1723,8 @@ struct drm_i915_private { struct work_struct idle_work; } gem; + u8 pch_ssc_use; + /* For i945gm vblank irq vs. C3 workaround */ struct { struct work_struct work; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 95e7c52cf8edc430e5c77bd866a8db183e29907c..d0f94f239919e1fefdd6df3e0a4270f7a8fd8952 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -969,6 +969,9 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, lockdep_assert_held(&obj->base.dev->struct_mutex); + if (i915_gem_object_never_bind_ggtt(obj)) + return ERR_PTR(-ENODEV); + if (flags & PIN_MAPPABLE && (!view || view->type == I915_GGTT_VIEW_NORMAL)) { /* If the required space is larger than the available diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 663ff9f4fac973811bcaa930a574eb27e3c71de0..1e7b1be25bb07a1d6ac2b7134dded4fdac23c68a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -26,6 +26,8 @@ #include "dsi_cfg.h" #include "msm_kms.h" +#define DSI_RESET_TOGGLE_DELAY_MS 20 + static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor) { u32 ver; @@ -986,7 +988,7 @@ static void dsi_sw_reset(struct msm_dsi_host *msm_host) wmb(); /* clocks need to be enabled before reset */ dsi_write(msm_host, REG_DSI_RESET, 1); - wmb(); /* make sure reset happen */ + msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */ dsi_write(msm_host, REG_DSI_RESET, 0); } @@ -1396,7 +1398,7 @@ static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host) /* dsi controller can only be reset while clocks are running */ dsi_write(msm_host, REG_DSI_RESET, 1); - wmb(); /* make sure reset happen */ + msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */ dsi_write(msm_host, REG_DSI_RESET, 0); wmb(); /* controller out of reset */ dsi_write(msm_host, REG_DSI_CTRL, data0); diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index bc2ddeb55f5d86ffbc9cbe1a39e2e90d77ce60df..f21bc8a7ee3a2fe7d6cdef0747079cf450dc6e6d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -556,11 +556,11 @@ static int panfrost_probe(struct platform_device *pdev) return 0; err_out2: + pm_runtime_disable(pfdev->dev); panfrost_devfreq_fini(pfdev); err_out1: panfrost_device_fini(pfdev); err_out0: - pm_runtime_disable(pfdev->dev); drm_dev_put(ddev); return err; } diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index f67ed925c0eff63b2c171dab1fd91574342b516b..8822ec13a0d619f26d9f22fe54321dbfefc88daf 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -208,6 +208,9 @@ static void panfrost_gpu_init_features(struct panfrost_device *pfdev) pfdev->features.mem_features = gpu_read(pfdev, GPU_MEM_FEATURES); pfdev->features.mmu_features = gpu_read(pfdev, GPU_MMU_FEATURES); pfdev->features.thread_features = gpu_read(pfdev, GPU_THREAD_FEATURES); + pfdev->features.max_threads = gpu_read(pfdev, GPU_THREAD_MAX_THREADS); + pfdev->features.thread_max_workgroup_sz = gpu_read(pfdev, GPU_THREAD_MAX_WORKGROUP_SIZE); + pfdev->features.thread_max_barrier_sz = gpu_read(pfdev, GPU_THREAD_MAX_BARRIER_SIZE); pfdev->features.coherency_features = gpu_read(pfdev, GPU_COHERENCY_FEATURES); for (i = 0; i < 4; i++) pfdev->features.texture_features[i] = gpu_read(pfdev, GPU_TEXTURE_FEATURES(i)); diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index a58551668d9aa8d5c452befbe1796d2f1f23b587..21f34d44aac2c01fcbce39e233bf1115df4f3cd6 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -381,13 +381,19 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) job_read(pfdev, JS_TAIL_LO(js)), sched_job); - mutex_lock(&pfdev->reset_lock); + if (!mutex_trylock(&pfdev->reset_lock)) + return; - for (i = 0; i < NUM_JOB_SLOTS; i++) - drm_sched_stop(&pfdev->js->queue[i].sched, sched_job); + for (i = 0; i < NUM_JOB_SLOTS; i++) { + struct drm_gpu_scheduler *sched = &pfdev->js->queue[i].sched; + + drm_sched_stop(sched, sched_job); + if (js != i) + /* Ensure any timeouts on other slots have finished */ + cancel_delayed_work_sync(&sched->work_tdr); + } - if (sched_job) - drm_sched_increase_karma(sched_job); + drm_sched_increase_karma(sched_job); spin_lock_irqsave(&pfdev->js->job_lock, flags); for (i = 0; i < NUM_JOB_SLOTS; i++) { diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index bdd99056847689c2c88fe67d1435e84662cd0eb6..a3ed64a1f15ecd8fd686b99fce496ddb760ed938 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -224,9 +224,9 @@ static size_t get_pgsize(u64 addr, size_t size) return SZ_2M; } -void panfrost_mmu_flush_range(struct panfrost_device *pfdev, - struct panfrost_mmu *mmu, - u64 iova, size_t size) +static void panfrost_mmu_flush_range(struct panfrost_device *pfdev, + struct panfrost_mmu *mmu, + u64 iova, size_t size) { if (mmu->as < 0) return; @@ -406,11 +406,11 @@ addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr) spin_lock(&pfdev->as_lock); list_for_each_entry(mmu, &pfdev->as_lru_list, list) { if (as == mmu->as) - break; + goto found_mmu; } - if (as != mmu->as) - goto out; + goto out; +found_mmu: priv = container_of(mmu, struct panfrost_file_priv, mmu); spin_lock(&priv->mm_lock); @@ -432,7 +432,8 @@ addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr) #define NUM_FAULT_PAGES (SZ_2M / PAGE_SIZE) -int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, u64 addr) +static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, + u64 addr) { int ret, i; struct panfrost_gem_object *bo; diff --git a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c index 83c57d325ca8754519b4949ca817c9187018db16..2dba192bf198454982d54ab9403f253e0529c652 100644 --- a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +++ b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c @@ -16,6 +16,7 @@ #include "panfrost_issues.h" #include "panfrost_job.h" #include "panfrost_mmu.h" +#include "panfrost_perfcnt.h" #include "panfrost_regs.h" #define COUNTERS_PER_BLOCK 64 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index d0bc91ed7c90a73b898e57a6a77a4786c11ed169..4528f4dc0b2d5e4f7fbd3c635ddef9f050f05292 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -379,7 +379,9 @@ radeon_pci_remove(struct pci_dev *pdev) static void radeon_pci_shutdown(struct pci_dev *pdev) { +#ifdef CONFIG_PPC64 struct drm_device *ddev = pci_get_drvdata(pdev); +#endif /* if we are running in a VM, make sure the device * torn down properly on reboot/shutdown @@ -387,11 +389,15 @@ radeon_pci_shutdown(struct pci_dev *pdev) if (radeon_device_is_virtual()) radeon_pci_remove(pdev); +#ifdef CONFIG_PPC64 /* Some adapters need to be suspended before a - * shutdown occurs in order to prevent an error - * during kexec. - */ + * shutdown occurs in order to prevent an error + * during kexec. + * Make this power specific becauase it breaks + * some non-power boards. + */ radeon_suspend_kms(ddev, true, true, false); +#endif } static int radeon_pmops_suspend(struct device *dev) diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 9a0ee74d82dc2b6c39859781c44e4e4be615cd1e..f39b97ed4ade4db6730fb5a31029c16701fd1d7d 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -479,6 +479,7 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched) struct drm_sched_job *s_job, *tmp; uint64_t guilty_context; bool found_guilty = false; + struct dma_fence *fence; list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) { struct drm_sched_fence *s_fence = s_job->s_fence; @@ -492,7 +493,16 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched) dma_fence_set_error(&s_fence->finished, -ECANCELED); dma_fence_put(s_job->s_fence->parent); - s_job->s_fence->parent = sched->ops->run_job(s_job); + fence = sched->ops->run_job(s_job); + + if (IS_ERR_OR_NULL(fence)) { + s_job->s_fence->parent = NULL; + dma_fence_set_error(&s_fence->finished, PTR_ERR(fence)); + } else { + s_job->s_fence->parent = fence; + } + + } } EXPORT_SYMBOL(drm_sched_resubmit_jobs); @@ -720,7 +730,7 @@ static int drm_sched_main(void *param) fence = sched->ops->run_job(sched_job); drm_sched_fence_scheduled(s_fence); - if (fence) { + if (!IS_ERR_OR_NULL(fence)) { s_fence->parent = dma_fence_get(fence); r = dma_fence_add_callback(fence, &sched_job->cb, drm_sched_process_job); @@ -730,8 +740,11 @@ static int drm_sched_main(void *param) DRM_ERROR("fence add callback failed (%d)\n", r); dma_fence_put(fence); - } else + } else { + + dma_fence_set_error(&s_fence->finished, PTR_ERR(fence)); drm_sched_process_job(NULL, &sched_job->cb); + } wake_up(&sched->job_scheduled); } diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 504763423d463a69122e3fe92870c8bec8b63aad..a46ac284dd5e9211070dcf1ecea877bdde90a760 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -63,7 +63,6 @@ config TINYDRM_REPAPER depends on DRM && SPI select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER - depends on THERMAL || !THERMAL help DRM driver for the following Pervasive Displays panels: 1.44" TFT EPD Panel (E1144CS021) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 20ff56f27aa4a988471ce390fd4149a6ec54343d..98819462f025fca646894d7245d136e75619d365 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -185,8 +185,9 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, list_add_tail(&bo->lru, &man->lru[bo->priority]); kref_get(&bo->list_kref); - if (bo->ttm && !(bo->ttm->page_flags & - (TTM_PAGE_FLAG_SG | TTM_PAGE_FLAG_SWAPPED))) { + if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm && + !(bo->ttm->page_flags & (TTM_PAGE_FLAG_SG | + TTM_PAGE_FLAG_SWAPPED))) { list_add_tail(&bo->swap, &bdev->glob->swap_lru[bo->priority]); kref_get(&bo->list_kref); } @@ -878,11 +879,11 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, if (!bo) { if (busy_bo) - ttm_bo_get(busy_bo); + kref_get(&busy_bo->list_kref); spin_unlock(&glob->lru_lock); ret = ttm_mem_evict_wait_busy(busy_bo, ctx, ticket); if (busy_bo) - ttm_bo_put(busy_bo); + kref_put(&busy_bo->list_kref, ttm_bo_release_list); return ret; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 76eedb9636931da799fe0954b6ef564ed7219621..46dc3de7e81bfba47037eea2a2dfbdd10e2b1313 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -278,15 +278,13 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) else ret = vmf_insert_pfn(&cvma, address, pfn); - /* - * Somebody beat us to this PTE or prefaulting to - * an already populated PTE, or prefaulting error. - */ - - if (unlikely((ret == VM_FAULT_NOPAGE && i > 0))) - break; - else if (unlikely(ret & VM_FAULT_ERROR)) - goto out_io_unlock; + /* Never error on prefaulted PTEs */ + if (unlikely((ret & VM_FAULT_ERROR))) { + if (i == 0) + goto out_io_unlock; + else + break; + } address += PAGE_SIZE; if (unlikely(++page_offset >= page_last)) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 5d80507b539bd01a28619629c7dd6cf9d4ddf42c..19c092d75266b451c05f5e095ef6b8150782a68a 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -557,13 +557,16 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, if (args->bcl_start != args->bcl_end) { bin = kcalloc(1, sizeof(*bin), GFP_KERNEL); - if (!bin) + if (!bin) { + v3d_job_put(&render->base); return -ENOMEM; + } ret = v3d_job_init(v3d, file_priv, &bin->base, v3d_job_free, args->in_sync_bcl); if (ret) { v3d_job_put(&render->base); + kfree(bin); return ret; } diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index 6654c1550e2e7af9e73b439ae6b7cc45ee31cc88..fbe4e16ab0297f778402eca7d9e44d2621bd1154 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c @@ -63,13 +63,20 @@ static int axff_init(struct hid_device *hid) { struct axff_device *axff; struct hid_report *report; - struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + struct hid_input *hidinput; struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; + struct input_dev *dev; int field_count = 0; int i, j; int error; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + dev = hidinput->input; + if (list_empty(report_list)) { hid_err(hid, "no output reports found\n"); return -ENODEV; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3eaee2c37931bad846decfa127bb905c134770e9..63fdbf09b044f3c8b0211d7e46c25ffa39776eb0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1139,6 +1139,7 @@ int hid_open_report(struct hid_device *device) __u8 *start; __u8 *buf; __u8 *end; + __u8 *next; int ret; static int (*dispatch_type[])(struct hid_parser *parser, struct hid_item *item) = { @@ -1192,7 +1193,8 @@ int hid_open_report(struct hid_device *device) device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; ret = -EINVAL; - while ((start = fetch_item(start, end, &item)) != NULL) { + while ((next = fetch_item(start, end, &item)) != NULL) { + start = next; if (item.format != HID_ITEM_FORMAT_SHORT) { hid_err(device, "unexpected long global item\n"); @@ -1230,7 +1232,8 @@ int hid_open_report(struct hid_device *device) } } - hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); + hid_err(device, "item fetching failed at offset %u/%u\n", + size - (unsigned int)(end - start), size); err: kfree(parser->collection_stack); alloc_err: diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index 17e17f9a597b5d9edc35b6f85c5b4b3db13e8727..947f19f8685f8668ea6e5568d3dad821156c3fa3 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c @@ -75,13 +75,19 @@ static int drff_init(struct hid_device *hid) { struct drff_device *drff; struct hid_report *report; - struct hid_input *hidinput = list_first_entry(&hid->inputs, - struct hid_input, list); + struct hid_input *hidinput; struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; + struct input_dev *dev; int error; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + dev = hidinput->input; + if (list_empty(report_list)) { hid_err(hid, "no output reports found\n"); return -ENODEV; diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c index 7cd5651872d3bd8b8c20455608914322a86c7185..c34f2e5a049f4dd314c72435d41398b2b87b0431 100644 --- a/drivers/hid/hid-emsff.c +++ b/drivers/hid/hid-emsff.c @@ -47,13 +47,19 @@ static int emsff_init(struct hid_device *hid) { struct emsff_device *emsff; struct hid_report *report; - struct hid_input *hidinput = list_first_entry(&hid->inputs, - struct hid_input, list); + struct hid_input *hidinput; struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; + struct input_dev *dev; int error; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + dev = hidinput->input; + if (list_empty(report_list)) { hid_err(hid, "no output reports found\n"); return -ENODEV; diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c index 0f95c96b70f810114f770d129dd3dd66a12185c6..ecbd3995a4eb1940c689c23ccbda5437f17d237d 100644 --- a/drivers/hid/hid-gaff.c +++ b/drivers/hid/hid-gaff.c @@ -64,14 +64,20 @@ static int gaff_init(struct hid_device *hid) { struct gaff_device *gaff; struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); + struct hid_input *hidinput; struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct list_head *report_ptr = report_list; - struct input_dev *dev = hidinput->input; + struct input_dev *dev; int error; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + if (list_empty(report_list)) { hid_err(hid, "no output reports found\n"); return -ENODEV; diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index 84f8c127ebdc745b61723b7ee2dffb532ce599a2..d86a9189e88fd0b56fc9b088313765a151c12f40 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -469,6 +469,10 @@ static int hammer_probe(struct hid_device *hdev, static const struct hid_device_id hammer_devices[] = { { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c index 10a7205588303d5180ef0b4fdecdba93d7d6b2f5..8619b80c834cc0b3c609eed7528b79f60f871ba2 100644 --- a/drivers/hid/hid-holtekff.c +++ b/drivers/hid/hid-holtekff.c @@ -124,13 +124,19 @@ static int holtekff_init(struct hid_device *hid) { struct holtekff_device *holtekff; struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); + struct hid_input *hidinput; struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; + struct input_dev *dev; int error; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + if (list_empty(report_list)) { hid_err(hid, "no output report found\n"); return -ENODEV; diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 76969a22b0f2f796a2b424ed252a8c0d08c3e3bd..447e8db21174ae78d35e372868d9234a31318963 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -476,6 +476,8 @@ #define USB_DEVICE_ID_GOOGLE_STAFF 0x502b #define USB_DEVICE_ID_GOOGLE_WAND 0x502d #define USB_DEVICE_ID_GOOGLE_WHISKERS 0x5030 +#define USB_DEVICE_ID_GOOGLE_MASTERBALL 0x503c +#define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d #define USB_VENDOR_ID_GOTOP 0x08f2 #define USB_DEVICE_ID_SUPER_Q2 0x007f diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index dd1a6c3a7de67464cec36e48fd89fc9e9a66d02c..73d07e35f12aa73dd58714c1792e7e00677b6f2b 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -50,11 +50,17 @@ int lg2ff_init(struct hid_device *hid) { struct lg2ff_device *lg2ff; struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct input_dev *dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *dev; int error; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + /* Check that the report looks ok */ report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); if (!report) diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index 9ecb6fd062030eb3ea21aab9d99a81c2172ed4d4..b7e1949f3cf779de12accc337981406dd1910f26 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c @@ -117,12 +117,19 @@ static const signed short ff3_joystick_ac[] = { int lg3ff_init(struct hid_device *hid) { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct input_dev *dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *dev; const signed short *ff_bits = ff3_joystick_ac; int error; int i; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + /* Check that the report looks ok */ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) return -ENODEV; diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 03f0220062cab641a725eddc2e4d51c1bedca141..5e6a0cef2a06d061035520a28e24cc4488859498 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -1253,8 +1253,8 @@ static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_produc int lg4ff_init(struct hid_device *hid) { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct input_dev *dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *dev; struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); @@ -1266,6 +1266,13 @@ int lg4ff_init(struct hid_device *hid) int mmode_ret, mmode_idx = -1; u16 real_product_id; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + /* Check that the report looks ok */ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) return -1; diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index c79a6ec437450029f4490ed4e4dfe9ac1f280d2e..aed4ddc397a963154a041487e8d3c8c455b4cbdd 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -115,12 +115,19 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) int lgff_init(struct hid_device* hid) { - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct input_dev *dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *dev; const signed short *ff_bits = ff_joystick; int error; int i; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + /* Check that the report looks ok */ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) return -ENODEV; diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 0179f7ed77e5b13f852f4c4fb3fa9619f1c15677..8e91e2f06cb4fc8574e08ca3c8ddd2b4595767e3 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -1669,6 +1669,7 @@ static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev, #define HIDPP_FF_EFFECTID_NONE -1 #define HIDPP_FF_EFFECTID_AUTOCENTER -2 +#define HIDPP_AUTOCENTER_PARAMS_LENGTH 18 #define HIDPP_FF_MAX_PARAMS 20 #define HIDPP_FF_RESERVED_SLOTS 1 @@ -2009,7 +2010,7 @@ static int hidpp_ff_erase_effect(struct input_dev *dev, int effect_id) static void hidpp_ff_set_autocenter(struct input_dev *dev, u16 magnitude) { struct hidpp_ff_private_data *data = dev->ff->private; - u8 params[18]; + u8 params[HIDPP_AUTOCENTER_PARAMS_LENGTH]; dbg_hid("Setting autocenter to %d.\n", magnitude); @@ -2077,23 +2078,34 @@ static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, hidpp static void hidpp_ff_destroy(struct ff_device *ff) { struct hidpp_ff_private_data *data = ff->private; + struct hid_device *hid = data->hidpp->hid_dev; + hid_info(hid, "Unloading HID++ force feedback.\n"); + + device_remove_file(&hid->dev, &dev_attr_range); + destroy_workqueue(data->wq); kfree(data->effect_ids); } -static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) +static int hidpp_ff_init(struct hidpp_device *hidpp, + struct hidpp_ff_private_data *data) { struct hid_device *hid = hidpp->hid_dev; - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct input_dev *dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *dev; const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice); struct ff_device *ff; - struct hidpp_report response; - struct hidpp_ff_private_data *data; - int error, j, num_slots; + int error, j, num_slots = data->num_effects; u8 version; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + if (!dev) { hid_err(hid, "Struct input_dev not set!\n"); return -EINVAL; @@ -2109,27 +2121,17 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) for (j = 0; hidpp_ff_effects_v2[j] >= 0; j++) set_bit(hidpp_ff_effects_v2[j], dev->ffbit); - /* Read number of slots available in device */ - error = hidpp_send_fap_command_sync(hidpp, feature_index, - HIDPP_FF_GET_INFO, NULL, 0, &response); - if (error) { - if (error < 0) - return error; - hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", - __func__, error); - return -EPROTO; - } - - num_slots = response.fap.params[0] - HIDPP_FF_RESERVED_SLOTS; - error = input_ff_create(dev, num_slots); if (error) { hid_err(dev, "Failed to create FF device!\n"); return error; } - - data = kzalloc(sizeof(*data), GFP_KERNEL); + /* + * Create a copy of passed data, so we can transfer memory + * ownership to FF core + */ + data = kmemdup(data, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; data->effect_ids = kcalloc(num_slots, sizeof(int), GFP_KERNEL); @@ -2145,10 +2147,7 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) } data->hidpp = hidpp; - data->feature_index = feature_index; data->version = version; - data->slot_autocenter = 0; - data->num_effects = num_slots; for (j = 0; j < num_slots; j++) data->effect_ids[j] = -1; @@ -2162,68 +2161,20 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) ff->set_autocenter = hidpp_ff_set_autocenter; ff->destroy = hidpp_ff_destroy; - - /* reset all forces */ - error = hidpp_send_fap_command_sync(hidpp, feature_index, - HIDPP_FF_RESET_ALL, NULL, 0, &response); - - /* Read current Range */ - error = hidpp_send_fap_command_sync(hidpp, feature_index, - HIDPP_FF_GET_APERTURE, NULL, 0, &response); - if (error) - hid_warn(hidpp->hid_dev, "Failed to read range from device!\n"); - data->range = error ? 900 : get_unaligned_be16(&response.fap.params[0]); - /* Create sysfs interface */ error = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range); if (error) hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d!\n", error); - /* Read the current gain values */ - error = hidpp_send_fap_command_sync(hidpp, feature_index, - HIDPP_FF_GET_GLOBAL_GAINS, NULL, 0, &response); - if (error) - hid_warn(hidpp->hid_dev, "Failed to read gain values from device!\n"); - data->gain = error ? 0xffff : get_unaligned_be16(&response.fap.params[0]); - /* ignore boost value at response.fap.params[2] */ - /* init the hardware command queue */ atomic_set(&data->workqueue_size, 0); - /* initialize with zero autocenter to get wheel in usable state */ - hidpp_ff_set_autocenter(dev, 0); - hid_info(hid, "Force feedback support loaded (firmware release %d).\n", version); return 0; } -static int hidpp_ff_deinit(struct hid_device *hid) -{ - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct input_dev *dev = hidinput->input; - struct hidpp_ff_private_data *data; - - if (!dev) { - hid_err(hid, "Struct input_dev not found!\n"); - return -EINVAL; - } - - hid_info(hid, "Unloading HID++ force feedback.\n"); - data = dev->ff->private; - if (!data) { - hid_err(hid, "Private data not found!\n"); - return -EINVAL; - } - - destroy_workqueue(data->wq); - device_remove_file(&hid->dev, &dev_attr_range); - - return 0; -} - - /* ************************************************************************** */ /* */ /* Device Support */ @@ -2725,24 +2676,93 @@ static int k400_connect(struct hid_device *hdev, bool connected) #define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123 -static int g920_get_config(struct hidpp_device *hidpp) +static int g920_ff_set_autocenter(struct hidpp_device *hidpp, + struct hidpp_ff_private_data *data) { + struct hidpp_report response; + u8 params[HIDPP_AUTOCENTER_PARAMS_LENGTH] = { + [1] = HIDPP_FF_EFFECT_SPRING | HIDPP_FF_EFFECT_AUTOSTART, + }; + int ret; + + /* initialize with zero autocenter to get wheel in usable state */ + + dbg_hid("Setting autocenter to 0.\n"); + ret = hidpp_send_fap_command_sync(hidpp, data->feature_index, + HIDPP_FF_DOWNLOAD_EFFECT, + params, ARRAY_SIZE(params), + &response); + if (ret) + hid_warn(hidpp->hid_dev, "Failed to autocenter device!\n"); + else + data->slot_autocenter = response.fap.params[0]; + + return ret; +} + +static int g920_get_config(struct hidpp_device *hidpp, + struct hidpp_ff_private_data *data) +{ + struct hidpp_report response; u8 feature_type; - u8 feature_index; int ret; + memset(data, 0, sizeof(*data)); + /* Find feature and store for later use */ ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK, - &feature_index, &feature_type); + &data->feature_index, &feature_type); if (ret) return ret; - ret = hidpp_ff_init(hidpp, feature_index); + /* Read number of slots available in device */ + ret = hidpp_send_fap_command_sync(hidpp, data->feature_index, + HIDPP_FF_GET_INFO, + NULL, 0, + &response); + if (ret) { + if (ret < 0) + return ret; + hid_err(hidpp->hid_dev, + "%s: received protocol error 0x%02x\n", __func__, ret); + return -EPROTO; + } + + data->num_effects = response.fap.params[0] - HIDPP_FF_RESERVED_SLOTS; + + /* reset all forces */ + ret = hidpp_send_fap_command_sync(hidpp, data->feature_index, + HIDPP_FF_RESET_ALL, + NULL, 0, + &response); if (ret) - hid_warn(hidpp->hid_dev, "Unable to initialize force feedback support, errno %d\n", - ret); + hid_warn(hidpp->hid_dev, "Failed to reset all forces!\n"); - return 0; + ret = hidpp_send_fap_command_sync(hidpp, data->feature_index, + HIDPP_FF_GET_APERTURE, + NULL, 0, + &response); + if (ret) { + hid_warn(hidpp->hid_dev, + "Failed to read range from device!\n"); + } + data->range = ret ? + 900 : get_unaligned_be16(&response.fap.params[0]); + + /* Read the current gain values */ + ret = hidpp_send_fap_command_sync(hidpp, data->feature_index, + HIDPP_FF_GET_GLOBAL_GAINS, + NULL, 0, + &response); + if (ret) + hid_warn(hidpp->hid_dev, + "Failed to read gain values from device!\n"); + data->gain = ret ? + 0xffff : get_unaligned_be16(&response.fap.params[0]); + + /* ignore boost value at response.fap.params[2] */ + + return g920_ff_set_autocenter(hidpp, data); } /* -------------------------------------------------------------------------- */ @@ -3458,34 +3478,45 @@ static int hidpp_get_report_length(struct hid_device *hdev, int id) return report->field[0]->report_count + 1; } -static bool hidpp_validate_report(struct hid_device *hdev, int id, - int expected_length, bool optional) +static bool hidpp_validate_device(struct hid_device *hdev) { - int report_length; + struct hidpp_device *hidpp = hid_get_drvdata(hdev); + int id, report_length, supported_reports = 0; - if (id >= HID_MAX_IDS || id < 0) { - hid_err(hdev, "invalid HID report id %u\n", id); - return false; + id = REPORT_ID_HIDPP_SHORT; + report_length = hidpp_get_report_length(hdev, id); + if (report_length) { + if (report_length < HIDPP_REPORT_SHORT_LENGTH) + goto bad_device; + + supported_reports++; } + id = REPORT_ID_HIDPP_LONG; report_length = hidpp_get_report_length(hdev, id); - if (!report_length) - return optional; + if (report_length) { + if (report_length < HIDPP_REPORT_LONG_LENGTH) + goto bad_device; - if (report_length < expected_length) { - hid_warn(hdev, "not enough values in hidpp report %d\n", id); - return false; + supported_reports++; } - return true; -} + id = REPORT_ID_HIDPP_VERY_LONG; + report_length = hidpp_get_report_length(hdev, id); + if (report_length) { + if (report_length < HIDPP_REPORT_LONG_LENGTH || + report_length > HIDPP_REPORT_VERY_LONG_MAX_LENGTH) + goto bad_device; -static bool hidpp_validate_device(struct hid_device *hdev) -{ - return hidpp_validate_report(hdev, REPORT_ID_HIDPP_SHORT, - HIDPP_REPORT_SHORT_LENGTH, false) && - hidpp_validate_report(hdev, REPORT_ID_HIDPP_LONG, - HIDPP_REPORT_LONG_LENGTH, true); + supported_reports++; + hidpp->very_long_report_length = report_length; + } + + return supported_reports; + +bad_device: + hid_warn(hdev, "not enough values in hidpp report %d\n", id); + return false; } static bool hidpp_application_equals(struct hid_device *hdev, @@ -3505,6 +3536,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) int ret; bool connected; unsigned int connect_mask = HID_CONNECT_DEFAULT; + struct hidpp_ff_private_data data; /* report_fixup needs drvdata to be set before we call hid_parse */ hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL); @@ -3531,11 +3563,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) return hid_hw_start(hdev, HID_CONNECT_DEFAULT); } - hidpp->very_long_report_length = - hidpp_get_report_length(hdev, REPORT_ID_HIDPP_VERY_LONG); - if (hidpp->very_long_report_length > HIDPP_REPORT_VERY_LONG_MAX_LENGTH) - hidpp->very_long_report_length = HIDPP_REPORT_VERY_LONG_MAX_LENGTH; - if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE) hidpp->quirks |= HIDPP_QUIRK_UNIFYING; @@ -3614,7 +3641,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (ret) goto hid_hw_init_fail; } else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) { - ret = g920_get_config(hidpp); + ret = g920_get_config(hidpp, &data); if (ret) goto hid_hw_init_fail; } @@ -3636,6 +3663,14 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) goto hid_hw_start_fail; } + if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { + ret = hidpp_ff_init(hidpp, &data); + if (ret) + hid_warn(hidpp->hid_dev, + "Unable to initialize force feedback support, errno %d\n", + ret); + } + return ret; hid_hw_init_fail: @@ -3658,9 +3693,6 @@ static void hidpp_remove(struct hid_device *hdev) sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group); - if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) - hidpp_ff_deinit(hdev); - hid_hw_stop(hdev); cancel_work_sync(&hidpp->work); mutex_destroy(&hidpp->send_mutex); diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 2cf83856f2e41c7e6c1456224988eaaa6a370e0f..2d8b589201a4e80c7d2dc7c4a6df35344840bd9a 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -328,11 +328,17 @@ static int ms_play_effect(struct input_dev *dev, void *data, static int ms_init_ff(struct hid_device *hdev) { - struct hid_input *hidinput = list_entry(hdev->inputs.next, - struct hid_input, list); - struct input_dev *input_dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *input_dev; struct ms_data *ms = hid_get_drvdata(hdev); + if (list_empty(&hdev->inputs)) { + hid_err(hdev, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hdev->inputs.next, struct hid_input, list); + input_dev = hidinput->input; + if (!(ms->quirks & MS_QUIRK_FF)) return 0; diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 5a3b3d974d849c28503f6f6390312384d6e1868f..2666af02d5c1a11f1a32f098eecb61ddc458cf0a 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -516,7 +516,7 @@ static void pcmidi_setup_extra_keys( MY PICTURES => KEY_WORDPROCESSOR MY MUSIC=> KEY_SPREADSHEET */ - unsigned int keys[] = { + static const unsigned int keys[] = { KEY_FN, KEY_MESSENGER, KEY_CALENDAR, KEY_ADDRESSBOOK, KEY_DOCUMENTS, @@ -532,7 +532,7 @@ static void pcmidi_setup_extra_keys( 0 }; - unsigned int *pkeys = &keys[0]; + const unsigned int *pkeys = &keys[0]; unsigned short i; if (pm->ifnum != 1) /* only set up ONCE for interace 1 */ diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 73c0f7a95e2dcea13d10b37176c9d7678074af1c..4c6ed6ef31f1e731be29d06239fe972cc2e4eb4b 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -2254,9 +2254,15 @@ static int sony_play_effect(struct input_dev *dev, void *data, static int sony_init_ff(struct sony_sc *sc) { - struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, - struct hid_input, list); - struct input_dev *input_dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *input_dev; + + if (list_empty(&sc->hdev->inputs)) { + hid_err(sc->hdev, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list); + input_dev = hidinput->input; input_set_capability(input_dev, EV_FF, FF_RUMBLE); return input_ff_create_memless(input_dev, NULL, sony_play_effect); diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index bdfc5ff3b2c5c9211291f71d8f0304e233f076bd..90acef3045369e15f72abd7c72580952f080c518 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c @@ -124,12 +124,18 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) struct tmff_device *tmff; struct hid_report *report; struct list_head *report_list; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct input_dev *input_dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *input_dev; int error; int i; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + input_dev = hidinput->input; + tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); if (!tmff) return -ENOMEM; diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index f90959e940287912e7b64ceed1eb2424f484455d..3abaca045869b0943d179a1af61be564ebdba299 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -54,11 +54,17 @@ static int zpff_init(struct hid_device *hid) { struct zpff_device *zpff; struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct input_dev *dev = hidinput->input; + struct hid_input *hidinput; + struct input_dev *dev; int i, error; + if (list_empty(&hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } + hidinput = list_entry(hid->inputs.next, struct hid_input, list); + dev = hidinput->input; + for (i = 0; i < 4; i++) { report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); if (!report) diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 2a7c6e33bb1c4322b6851e42988f593e69ae527f..d9c55e30f986b6e04927c2f94c20ceb387e0104c 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -48,8 +47,6 @@ /* quirks to control the device */ #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0) #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1) -#define I2C_HID_QUIRK_NO_RUNTIME_PM BIT(2) -#define I2C_HID_QUIRK_DELAY_AFTER_SLEEP BIT(3) #define I2C_HID_QUIRK_BOGUS_IRQ BIT(4) /* flags */ @@ -172,14 +169,7 @@ static const struct i2c_hid_quirks { { USB_VENDOR_ID_WEIDA, HID_ANY_ID, I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288, - I2C_HID_QUIRK_NO_IRQ_AFTER_RESET | - I2C_HID_QUIRK_NO_RUNTIME_PM }, - { I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_4B33, - I2C_HID_QUIRK_DELAY_AFTER_SLEEP }, - { USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001, - I2C_HID_QUIRK_NO_RUNTIME_PM }, - { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0, - I2C_HID_QUIRK_NO_RUNTIME_PM }, + I2C_HID_QUIRK_NO_IRQ_AFTER_RESET }, { USB_VENDOR_ID_ELAN, HID_ANY_ID, I2C_HID_QUIRK_BOGUS_IRQ }, { 0, 0 } @@ -397,7 +387,6 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state) { struct i2c_hid *ihid = i2c_get_clientdata(client); int ret; - unsigned long now, delay; i2c_hid_dbg(ihid, "%s\n", __func__); @@ -415,22 +404,9 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state) goto set_pwr_exit; } - if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP && - power_state == I2C_HID_PWR_ON) { - now = jiffies; - if (time_after(ihid->sleep_delay, now)) { - delay = jiffies_to_usecs(ihid->sleep_delay - now); - usleep_range(delay, delay + 1); - } - } - ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state, 0, NULL, 0, NULL, 0); - if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP && - power_state == I2C_HID_PWR_SLEEP) - ihid->sleep_delay = jiffies + msecs_to_jiffies(20); - if (ret) dev_err(&client->dev, "failed to change power setting.\n"); @@ -791,11 +767,6 @@ static int i2c_hid_open(struct hid_device *hid) { struct i2c_client *client = hid->driver_data; struct i2c_hid *ihid = i2c_get_clientdata(client); - int ret = 0; - - ret = pm_runtime_get_sync(&client->dev); - if (ret < 0) - return ret; set_bit(I2C_HID_STARTED, &ihid->flags); return 0; @@ -807,27 +778,6 @@ static void i2c_hid_close(struct hid_device *hid) struct i2c_hid *ihid = i2c_get_clientdata(client); clear_bit(I2C_HID_STARTED, &ihid->flags); - - /* Save some power */ - pm_runtime_put(&client->dev); -} - -static int i2c_hid_power(struct hid_device *hid, int lvl) -{ - struct i2c_client *client = hid->driver_data; - struct i2c_hid *ihid = i2c_get_clientdata(client); - - i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl); - - switch (lvl) { - case PM_HINT_FULLON: - pm_runtime_get_sync(&client->dev); - break; - case PM_HINT_NORMAL: - pm_runtime_put(&client->dev); - break; - } - return 0; } struct hid_ll_driver i2c_hid_ll_driver = { @@ -836,7 +786,6 @@ struct hid_ll_driver i2c_hid_ll_driver = { .stop = i2c_hid_stop, .open = i2c_hid_open, .close = i2c_hid_close, - .power = i2c_hid_power, .output_report = i2c_hid_output_report, .raw_request = i2c_hid_raw_request, }; @@ -1104,9 +1053,6 @@ static int i2c_hid_probe(struct i2c_client *client, i2c_hid_acpi_fix_up_power(&client->dev); - pm_runtime_get_noresume(&client->dev); - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); device_enable_async_suspend(&client->dev); /* Make sure there is something at this address */ @@ -1114,16 +1060,16 @@ static int i2c_hid_probe(struct i2c_client *client, if (ret < 0) { dev_dbg(&client->dev, "nothing at this address: %d\n", ret); ret = -ENXIO; - goto err_pm; + goto err_regulator; } ret = i2c_hid_fetch_hid_descriptor(ihid); if (ret < 0) - goto err_pm; + goto err_regulator; ret = i2c_hid_init_irq(client); if (ret < 0) - goto err_pm; + goto err_regulator; hid = hid_allocate_device(); if (IS_ERR(hid)) { @@ -1154,9 +1100,6 @@ static int i2c_hid_probe(struct i2c_client *client, goto err_mem_free; } - if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM)) - pm_runtime_put(&client->dev); - return 0; err_mem_free: @@ -1165,10 +1108,6 @@ static int i2c_hid_probe(struct i2c_client *client, err_irq: free_irq(client->irq, ihid); -err_pm: - pm_runtime_put_noidle(&client->dev); - pm_runtime_disable(&client->dev); - err_regulator: regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies), ihid->pdata.supplies); @@ -1181,12 +1120,6 @@ static int i2c_hid_remove(struct i2c_client *client) struct i2c_hid *ihid = i2c_get_clientdata(client); struct hid_device *hid; - if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM)) - pm_runtime_get_sync(&client->dev); - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); - hid = ihid->hid; hid_destroy_device(hid); @@ -1219,25 +1152,15 @@ static int i2c_hid_suspend(struct device *dev) int wake_status; if (hid->driver && hid->driver->suspend) { - /* - * Wake up the device so that IO issues in - * HID driver's suspend code can succeed. - */ - ret = pm_runtime_resume(dev); - if (ret < 0) - return ret; - ret = hid->driver->suspend(hid, PMSG_SUSPEND); if (ret < 0) return ret; } - if (!pm_runtime_suspended(dev)) { - /* Save some power */ - i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); + /* Save some power */ + i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); - disable_irq(client->irq); - } + disable_irq(client->irq); if (device_may_wakeup(&client->dev)) { wake_status = enable_irq_wake(client->irq); @@ -1279,11 +1202,6 @@ static int i2c_hid_resume(struct device *dev) wake_status); } - /* We'll resume to full power */ - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - enable_irq(client->irq); /* Instead of resetting device, simply powers the device on. This @@ -1304,30 +1222,8 @@ static int i2c_hid_resume(struct device *dev) } #endif -#ifdef CONFIG_PM -static int i2c_hid_runtime_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); - disable_irq(client->irq); - return 0; -} - -static int i2c_hid_runtime_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - enable_irq(client->irq); - i2c_hid_set_power(client, I2C_HID_PWR_ON); - return 0; -} -#endif - static const struct dev_pm_ops i2c_hid_pm = { SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume) - SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume, - NULL) }; static const struct i2c_device_id i2c_hid_id_table[] = { diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c index 75078c83be1af579c9e7ad804271d620d3849dc2..d31ea82b84c173033dd1a6582122ec9197671fbc 100644 --- a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c @@ -322,6 +322,25 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { }, .driver_data = (void *)&sipodev_desc }, + { + /* + * There are at least 2 Primebook C11B versions, the older + * version has a product-name of "Primebook C11B", and a + * bios version / release / firmware revision of: + * V2.1.2 / 05/03/2018 / 18.2 + * The new version has "PRIMEBOOK C11B" as product-name and a + * bios version / release / firmware revision of: + * CFALKSW05_BIOS_V1.1.2 / 11/19/2018 / 19.2 + * Only the older version needs this quirk, note the newer + * version will not match as it has a different product-name. + */ + .ident = "Trekstor Primebook C11B", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11B"), + }, + .driver_data = (void *)&sipodev_desc + }, { .ident = "Direkt-Tek DTLAPY116-2", .matches = { diff --git a/drivers/hid/intel-ish-hid/ishtp/client-buffers.c b/drivers/hid/intel-ish-hid/ishtp/client-buffers.c index 1b0a0cc605e7740d07d8e0fd8c976105abdfae2e..513d7a4a1b8acd176a673375d6f594c3820e116a 100644 --- a/drivers/hid/intel-ish-hid/ishtp/client-buffers.c +++ b/drivers/hid/intel-ish-hid/ishtp/client-buffers.c @@ -84,7 +84,7 @@ int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl) return 0; out: dev_err(&cl->device->dev, "error in allocating Tx pool\n"); - ishtp_cl_free_rx_ring(cl); + ishtp_cl_free_tx_ring(cl); return -ENOMEM; } diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 0037e2bdacd6b25ea2edca74fa7d11b542e0b843..8a51dcf055eab73222c828a64ba7c4a5b743aefb 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -170,7 +170,7 @@ static inline int ina3221_wait_for_data(struct ina3221_data *ina) /* Polling the CVRF bit to make sure read data is ready */ return regmap_field_read_poll_timeout(ina->fields[F_CVRF], - cvrf, cvrf, wait, 100000); + cvrf, cvrf, wait, wait * 2); } static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c index b26419dbe840cb467ba487f88dd630e118e0e103..281c81edabc65740df60c154b4b1e59c4c995fc7 100644 --- a/drivers/hwmon/nct7904.c +++ b/drivers/hwmon/nct7904.c @@ -82,6 +82,10 @@ #define FANCTL1_FMR_REG 0x00 /* Bank 3; 1 reg per channel */ #define FANCTL1_OUT_REG 0x10 /* Bank 3; 1 reg per channel */ +#define VOLT_MONITOR_MODE 0x0 +#define THERMAL_DIODE_MODE 0x1 +#define THERMISTOR_MODE 0x3 + #define ENABLE_TSI BIT(1) static const unsigned short normal_i2c[] = { @@ -935,11 +939,16 @@ static int nct7904_probe(struct i2c_client *client, for (i = 0; i < 4; i++) { val = (ret >> (i * 2)) & 0x03; bit = (1 << i); - if (val == 0) { + if (val == VOLT_MONITOR_MODE) { data->tcpu_mask &= ~bit; + } else if (val == THERMAL_DIODE_MODE && i < 2) { + data->temp_mode |= bit; + data->vsen_mask &= ~(0x06 << (i * 2)); + } else if (val == THERMISTOR_MODE) { + data->vsen_mask &= ~(0x02 << (i * 2)); } else { - if (val == 0x1 || val == 0x2) - data->temp_mode |= bit; + /* Reserved */ + data->tcpu_mask &= ~bit; data->vsen_mask &= ~(0x06 << (i * 2)); } } diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index fa66951b05d06670ffdb79ff7b1532574177594a..7b098ff5f5dd34b5bc9e8a0553a5afcd84b722a3 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -108,6 +108,12 @@ #define ASPEED_I2CD_S_TX_CMD BIT(2) #define ASPEED_I2CD_M_TX_CMD BIT(1) #define ASPEED_I2CD_M_START_CMD BIT(0) +#define ASPEED_I2CD_MASTER_CMDS_MASK \ + (ASPEED_I2CD_M_STOP_CMD | \ + ASPEED_I2CD_M_S_RX_CMD_LAST | \ + ASPEED_I2CD_M_RX_CMD | \ + ASPEED_I2CD_M_TX_CMD | \ + ASPEED_I2CD_M_START_CMD) /* 0x18 : I2CD Slave Device Address Register */ #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0) @@ -336,18 +342,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) struct i2c_msg *msg = &bus->msgs[bus->msgs_index]; u8 slave_addr = i2c_8bit_addr_from_msg(msg); - bus->master_state = ASPEED_I2C_MASTER_START; - #if IS_ENABLED(CONFIG_I2C_SLAVE) /* * If it's requested in the middle of a slave session, set the master * state to 'pending' then H/W will continue handling this master * command when the bus comes back to the idle state. */ - if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) + if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) { bus->master_state = ASPEED_I2C_MASTER_PENDING; + return; + } #endif /* CONFIG_I2C_SLAVE */ + bus->master_state = ASPEED_I2C_MASTER_START; bus->buf_index = 0; if (msg->flags & I2C_M_RD) { @@ -422,20 +429,6 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) } } -#if IS_ENABLED(CONFIG_I2C_SLAVE) - /* - * A pending master command will be started by H/W when the bus comes - * back to idle state after completing a slave operation so change the - * master state from 'pending' to 'start' at here if slave is inactive. - */ - if (bus->master_state == ASPEED_I2C_MASTER_PENDING) { - if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) - goto out_no_complete; - - bus->master_state = ASPEED_I2C_MASTER_START; - } -#endif /* CONFIG_I2C_SLAVE */ - /* Master is not currently active, irq was for someone else. */ if (bus->master_state == ASPEED_I2C_MASTER_INACTIVE || bus->master_state == ASPEED_I2C_MASTER_PENDING) @@ -462,11 +455,15 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) #if IS_ENABLED(CONFIG_I2C_SLAVE) /* * If a peer master starts a xfer immediately after it queues a - * master command, change its state to 'pending' then H/W will - * continue the queued master xfer just after completing the - * slave mode session. + * master command, clear the queued master command and change + * its state to 'pending'. To simplify handling of pending + * cases, it uses S/W solution instead of H/W command queue + * handling. */ if (unlikely(irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH)) { + writel(readl(bus->base + ASPEED_I2C_CMD_REG) & + ~ASPEED_I2CD_MASTER_CMDS_MASK, + bus->base + ASPEED_I2C_CMD_REG); bus->master_state = ASPEED_I2C_MASTER_PENDING; dev_dbg(bus->dev, "master goes pending due to a slave start\n"); @@ -629,6 +626,14 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id) irq_handled |= aspeed_i2c_master_irq(bus, irq_remaining); } + + /* + * Start a pending master command at here if a slave operation is + * completed. + */ + if (bus->master_state == ASPEED_I2C_MASTER_PENDING && + bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE) + aspeed_i2c_do_start(bus); #else irq_handled = aspeed_i2c_master_irq(bus, irq_remaining); #endif /* CONFIG_I2C_SLAVE */ @@ -691,6 +696,15 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap, ASPEED_I2CD_BUS_BUSY_STS)) aspeed_i2c_recover_bus(bus); + /* + * If timed out and the state is still pending, drop the pending + * master command. + */ + spin_lock_irqsave(&bus->lock, flags); + if (bus->master_state == ASPEED_I2C_MASTER_PENDING) + bus->master_state = ASPEED_I2C_MASTER_INACTIVE; + spin_unlock_irqrestore(&bus->lock, flags); + return -ETIMEDOUT; } diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 29eae1bf4f861a39078091644aa329326aa1c2ed..2152ec5f535c19316b0d7800afbf1bd3a44e5768 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -875,7 +875,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id) static u32 mtk_i2c_functionality(struct i2c_adapter *adap) { - if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN) + if (i2c_check_quirks(adap, I2C_AQ_NO_ZERO_LEN)) return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); else diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index d36cf08461f76d78edaff2250b21324b2996775c..b24e7b937f210bbb9fc5279f386c1f0e6044f528 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -305,7 +305,7 @@ struct stm32f7_i2c_dev { struct regmap *regmap; }; -/** +/* * All these values are coming from I2C Specification, Version 6.0, 4th of * April 2014. * @@ -1192,6 +1192,8 @@ static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev) STM32F7_I2C_CR1_TXIE; stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask); + /* Write 1st data byte */ + writel_relaxed(value, base + STM32F7_I2C_TXDR); } else { /* Notify i2c slave that new write transfer is starting */ i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); @@ -1501,7 +1503,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) void __iomem *base = i2c_dev->base; struct device *dev = i2c_dev->dev; struct stm32_i2c_dma *dma = i2c_dev->dma; - u32 mask, status; + u32 status; status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR); @@ -1526,12 +1528,15 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) f7_msg->result = -EINVAL; } - /* Disable interrupts */ - if (stm32f7_i2c_is_slave_registered(i2c_dev)) - mask = STM32F7_I2C_XFER_IRQ_MASK; - else - mask = STM32F7_I2C_ALL_IRQ_MASK; - stm32f7_i2c_disable_irq(i2c_dev, mask); + if (!i2c_dev->slave_running) { + u32 mask; + /* Disable interrupts */ + if (stm32f7_i2c_is_slave_registered(i2c_dev)) + mask = STM32F7_I2C_XFER_IRQ_MASK; + else + mask = STM32F7_I2C_ALL_IRQ_MASK; + stm32f7_i2c_disable_irq(i2c_dev, mask); + } /* Disable dma */ if (i2c_dev->use_dma) { diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index 3a8b0911c3bc16193032dcf1c678f18ded9d9f70..9d07378b5b4230f6e5f1568f3e6b428e95f7b98a 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -199,6 +199,7 @@ void ib_mad_cleanup(void); int ib_sa_init(void); void ib_sa_cleanup(void); +void rdma_nl_init(void); void rdma_nl_exit(void); int ib_nl_handle_resolve_resp(struct sk_buff *skb, diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 2dd2cfe9b56136f950fd9648120304e2b21a6904..50a92442c4f7c15ebc0708494cca898d3707c1cb 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -2716,6 +2716,8 @@ static int __init ib_core_init(void) goto err_comp_unbound; } + rdma_nl_init(); + ret = addr_init(); if (ret) { pr_warn("Could't init IB address resolution\n"); diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 72141c5b7c95d8701d66272fa0a697465f2103a8..ade71823370f3335566079599a76dde871cc9333 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -372,6 +372,7 @@ EXPORT_SYMBOL(iw_cm_disconnect); static void destroy_cm_id(struct iw_cm_id *cm_id) { struct iwcm_id_private *cm_id_priv; + struct ib_qp *qp; unsigned long flags; cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); @@ -389,6 +390,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id) set_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags); spin_lock_irqsave(&cm_id_priv->lock, flags); + qp = cm_id_priv->qp; + cm_id_priv->qp = NULL; + switch (cm_id_priv->state) { case IW_CM_STATE_LISTEN: cm_id_priv->state = IW_CM_STATE_DESTROYING; @@ -401,7 +405,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id) cm_id_priv->state = IW_CM_STATE_DESTROYING; spin_unlock_irqrestore(&cm_id_priv->lock, flags); /* Abrupt close of the connection */ - (void)iwcm_modify_qp_err(cm_id_priv->qp); + (void)iwcm_modify_qp_err(qp); spin_lock_irqsave(&cm_id_priv->lock, flags); break; case IW_CM_STATE_IDLE: @@ -426,11 +430,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id) BUG(); break; } - if (cm_id_priv->qp) { - cm_id_priv->id.device->ops.iw_rem_ref(cm_id_priv->qp); - cm_id_priv->qp = NULL; - } spin_unlock_irqrestore(&cm_id_priv->lock, flags); + if (qp) + cm_id_priv->id.device->ops.iw_rem_ref(qp); if (cm_id->mapped) { iwpm_remove_mapinfo(&cm_id->local_addr, &cm_id->m_local_addr); @@ -671,11 +673,11 @@ int iw_cm_accept(struct iw_cm_id *cm_id, BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_RECV); cm_id_priv->state = IW_CM_STATE_IDLE; spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id_priv->qp) { - cm_id->device->ops.iw_rem_ref(qp); - cm_id_priv->qp = NULL; - } + qp = cm_id_priv->qp; + cm_id_priv->qp = NULL; spin_unlock_irqrestore(&cm_id_priv->lock, flags); + if (qp) + cm_id->device->ops.iw_rem_ref(qp); clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); wake_up_all(&cm_id_priv->connect_wait); } @@ -696,7 +698,7 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) struct iwcm_id_private *cm_id_priv; int ret; unsigned long flags; - struct ib_qp *qp; + struct ib_qp *qp = NULL; cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); @@ -730,13 +732,13 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) return 0; /* success */ spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id_priv->qp) { - cm_id->device->ops.iw_rem_ref(qp); - cm_id_priv->qp = NULL; - } + qp = cm_id_priv->qp; + cm_id_priv->qp = NULL; cm_id_priv->state = IW_CM_STATE_IDLE; err: spin_unlock_irqrestore(&cm_id_priv->lock, flags); + if (qp) + cm_id->device->ops.iw_rem_ref(qp); clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); wake_up_all(&cm_id_priv->connect_wait); return ret; @@ -878,6 +880,7 @@ static int cm_conn_est_handler(struct iwcm_id_private *cm_id_priv, static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv, struct iw_cm_event *iw_event) { + struct ib_qp *qp = NULL; unsigned long flags; int ret; @@ -896,11 +899,13 @@ static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv, cm_id_priv->state = IW_CM_STATE_ESTABLISHED; } else { /* REJECTED or RESET */ - cm_id_priv->id.device->ops.iw_rem_ref(cm_id_priv->qp); + qp = cm_id_priv->qp; cm_id_priv->qp = NULL; cm_id_priv->state = IW_CM_STATE_IDLE; } spin_unlock_irqrestore(&cm_id_priv->lock, flags); + if (qp) + cm_id_priv->id.device->ops.iw_rem_ref(qp); ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event); if (iw_event->private_data_len) @@ -942,21 +947,18 @@ static void cm_disconnect_handler(struct iwcm_id_private *cm_id_priv, static int cm_close_handler(struct iwcm_id_private *cm_id_priv, struct iw_cm_event *iw_event) { + struct ib_qp *qp; unsigned long flags; - int ret = 0; + int ret = 0, notify_event = 0; spin_lock_irqsave(&cm_id_priv->lock, flags); + qp = cm_id_priv->qp; + cm_id_priv->qp = NULL; - if (cm_id_priv->qp) { - cm_id_priv->id.device->ops.iw_rem_ref(cm_id_priv->qp); - cm_id_priv->qp = NULL; - } switch (cm_id_priv->state) { case IW_CM_STATE_ESTABLISHED: case IW_CM_STATE_CLOSING: cm_id_priv->state = IW_CM_STATE_IDLE; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event); - spin_lock_irqsave(&cm_id_priv->lock, flags); + notify_event = 1; break; case IW_CM_STATE_DESTROYING: break; @@ -965,6 +967,10 @@ static int cm_close_handler(struct iwcm_id_private *cm_id_priv, } spin_unlock_irqrestore(&cm_id_priv->lock, flags); + if (qp) + cm_id_priv->id.device->ops.iw_rem_ref(qp); + if (notify_event) + ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event); return ret; } diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index 81dbd5f41beda241c1f815077fcad91a7f019f26..8cd31ef25eff20e3f54e5ab7f8f72243748062e2 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -42,9 +42,12 @@ #include #include "core_priv.h" -static DEFINE_MUTEX(rdma_nl_mutex); static struct { - const struct rdma_nl_cbs *cb_table; + const struct rdma_nl_cbs *cb_table; + /* Synchronizes between ongoing netlink commands and netlink client + * unregistration. + */ + struct rw_semaphore sem; } rdma_nl_types[RDMA_NL_NUM_CLIENTS]; bool rdma_nl_chk_listeners(unsigned int group) @@ -75,70 +78,53 @@ static bool is_nl_msg_valid(unsigned int type, unsigned int op) return (op < max_num_ops[type]) ? true : false; } -static bool -is_nl_valid(const struct sk_buff *skb, unsigned int type, unsigned int op) +static const struct rdma_nl_cbs * +get_cb_table(const struct sk_buff *skb, unsigned int type, unsigned int op) { const struct rdma_nl_cbs *cb_table; - if (!is_nl_msg_valid(type, op)) - return false; - /* * Currently only NLDEV client is supporting netlink commands in * non init_net net namespace. */ if (sock_net(skb->sk) != &init_net && type != RDMA_NL_NLDEV) - return false; + return NULL; - if (!rdma_nl_types[type].cb_table) { - mutex_unlock(&rdma_nl_mutex); - request_module("rdma-netlink-subsys-%d", type); - mutex_lock(&rdma_nl_mutex); - } + cb_table = READ_ONCE(rdma_nl_types[type].cb_table); + if (!cb_table) { + /* + * Didn't get valid reference of the table, attempt module + * load once. + */ + up_read(&rdma_nl_types[type].sem); - cb_table = rdma_nl_types[type].cb_table; + request_module("rdma-netlink-subsys-%d", type); + down_read(&rdma_nl_types[type].sem); + cb_table = READ_ONCE(rdma_nl_types[type].cb_table); + } if (!cb_table || (!cb_table[op].dump && !cb_table[op].doit)) - return false; - return true; + return NULL; + return cb_table; } void rdma_nl_register(unsigned int index, const struct rdma_nl_cbs cb_table[]) { - mutex_lock(&rdma_nl_mutex); - if (!is_nl_msg_valid(index, 0)) { - /* - * All clients are not interesting in success/failure of - * this call. They want to see the print to error log and - * continue their initialization. Print warning for them, - * because it is programmer's error to be here. - */ - mutex_unlock(&rdma_nl_mutex); - WARN(true, - "The not-valid %u index was supplied to RDMA netlink\n", - index); + if (WARN_ON(!is_nl_msg_valid(index, 0)) || + WARN_ON(READ_ONCE(rdma_nl_types[index].cb_table))) return; - } - - if (rdma_nl_types[index].cb_table) { - mutex_unlock(&rdma_nl_mutex); - WARN(true, - "The %u index is already registered in RDMA netlink\n", - index); - return; - } - rdma_nl_types[index].cb_table = cb_table; - mutex_unlock(&rdma_nl_mutex); + /* Pairs with the READ_ONCE in is_nl_valid() */ + smp_store_release(&rdma_nl_types[index].cb_table, cb_table); } EXPORT_SYMBOL(rdma_nl_register); void rdma_nl_unregister(unsigned int index) { - mutex_lock(&rdma_nl_mutex); + down_write(&rdma_nl_types[index].sem); rdma_nl_types[index].cb_table = NULL; - mutex_unlock(&rdma_nl_mutex); + up_write(&rdma_nl_types[index].sem); } EXPORT_SYMBOL(rdma_nl_unregister); @@ -170,15 +156,21 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, unsigned int index = RDMA_NL_GET_CLIENT(type); unsigned int op = RDMA_NL_GET_OP(type); const struct rdma_nl_cbs *cb_table; + int err = -EINVAL; - if (!is_nl_valid(skb, index, op)) + if (!is_nl_msg_valid(index, op)) return -EINVAL; - cb_table = rdma_nl_types[index].cb_table; + down_read(&rdma_nl_types[index].sem); + cb_table = get_cb_table(skb, index, op); + if (!cb_table) + goto done; if ((cb_table[op].flags & RDMA_NL_ADMIN_PERM) && - !netlink_capable(skb, CAP_NET_ADMIN)) - return -EPERM; + !netlink_capable(skb, CAP_NET_ADMIN)) { + err = -EPERM; + goto done; + } /* * LS responses overload the 0x100 (NLM_F_ROOT) flag. Don't @@ -186,8 +178,8 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, */ if (index == RDMA_NL_LS) { if (cb_table[op].doit) - return cb_table[op].doit(skb, nlh, extack); - return -EINVAL; + err = cb_table[op].doit(skb, nlh, extack); + goto done; } /* FIXME: Convert IWCM to properly handle doit callbacks */ if ((nlh->nlmsg_flags & NLM_F_DUMP) || index == RDMA_NL_IWCM) { @@ -195,14 +187,15 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, .dump = cb_table[op].dump, }; if (c.dump) - return netlink_dump_start(skb->sk, skb, nlh, &c); - return -EINVAL; + err = netlink_dump_start(skb->sk, skb, nlh, &c); + goto done; } if (cb_table[op].doit) - return cb_table[op].doit(skb, nlh, extack); - - return 0; + err = cb_table[op].doit(skb, nlh, extack); +done: + up_read(&rdma_nl_types[index].sem); + return err; } /* @@ -263,9 +256,7 @@ static int rdma_nl_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, static void rdma_nl_rcv(struct sk_buff *skb) { - mutex_lock(&rdma_nl_mutex); rdma_nl_rcv_skb(skb, &rdma_nl_rcv_msg); - mutex_unlock(&rdma_nl_mutex); } int rdma_nl_unicast(struct net *net, struct sk_buff *skb, u32 pid) @@ -297,6 +288,14 @@ int rdma_nl_multicast(struct net *net, struct sk_buff *skb, } EXPORT_SYMBOL(rdma_nl_multicast); +void rdma_nl_init(void) +{ + int idx; + + for (idx = 0; idx < RDMA_NL_NUM_CLIENTS; idx++) + init_rwsem(&rdma_nl_types[idx].sem); +} + void rdma_nl_exit(void) { int idx; diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index 65b36548bc17139b0a2fa5da51a4e0e7d4f9089f..c03af08b80e776688cfa3d4e303d37b1b992a7af 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -778,7 +778,7 @@ static int fill_res_counter_entry(struct sk_buff *msg, bool has_cap_net_admin, container_of(res, struct rdma_counter, res); if (port && port != counter->port) - return 0; + return -EAGAIN; /* Dump it even query failed */ rdma_counter_query_stats(counter); diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 1e5aeb39f774df6a1bc386ea448b89763ee1705f..63f7f7db590286a6e6bdc5d4d5cd037bb841294b 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -98,7 +98,7 @@ ib_uverbs_init_udata_buf_or_null(struct ib_udata *udata, struct ib_uverbs_device { atomic_t refcount; - int num_comp_vectors; + u32 num_comp_vectors; struct completion comp; struct device dev; /* First group for device attributes, NULL terminated array */ diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index f974b68542245206936e623a6d62d6ef948cecce..35c2841a569e98e73229bc80a99d8f350c00cda7 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -662,16 +662,17 @@ static bool find_gid_index(const union ib_gid *gid, void *context) { struct find_gid_index_context *ctx = context; + u16 vlan_id = 0xffff; + int ret; if (ctx->gid_type != gid_attr->gid_type) return false; - if ((!!(ctx->vlan_id != 0xffff) == !is_vlan_dev(gid_attr->ndev)) || - (is_vlan_dev(gid_attr->ndev) && - vlan_dev_vlan_id(gid_attr->ndev) != ctx->vlan_id)) + ret = rdma_read_gid_l2_fields(gid_attr, &vlan_id, NULL); + if (ret) return false; - return true; + return ctx->vlan_id == vlan_id; } static const struct ib_gid_attr * diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index e87fc0408470452c4bc5600c127f69848c2c3cb3..347dc242fb8829eab1fca133e61da178cad78081 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -495,7 +495,6 @@ static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); release_ep_resources(ep); - kfree_skb(skb); return 0; } @@ -506,7 +505,6 @@ static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))); c4iw_put_ep(&ep->parent_ep->com); release_ep_resources(ep); - kfree_skb(skb); return 0; } @@ -2424,20 +2422,6 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type; pr_debug("ep %p tid %u\n", ep, ep->hwtid); - - skb_get(skb); - rpl = cplhdr(skb); - if (!is_t4(adapter_type)) { - skb_trim(skb, roundup(sizeof(*rpl5), 16)); - rpl5 = (void *)rpl; - INIT_TP_WR(rpl5, ep->hwtid); - } else { - skb_trim(skb, sizeof(*rpl)); - INIT_TP_WR(rpl, ep->hwtid); - } - OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, - ep->hwtid)); - cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, enable_tcp_timestamps && req->tcpopt.tstamp, (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1); @@ -2483,6 +2467,20 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb, if (tcph->ece && tcph->cwr) opt2 |= CCTRL_ECN_V(1); } + + skb_get(skb); + rpl = cplhdr(skb); + if (!is_t4(adapter_type)) { + skb_trim(skb, roundup(sizeof(*rpl5), 16)); + rpl5 = (void *)rpl; + INIT_TP_WR(rpl5, ep->hwtid); + } else { + skb_trim(skb, sizeof(*rpl)); + INIT_TP_WR(rpl, ep->hwtid); + } + OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL, + ep->hwtid)); + if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) { u32 isn = (prandom_u32() & ~7UL) - 1; opt2 |= T5_OPT_2_VALID_F; diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index 2ed7bfd5feea6a5ec5206ac77ff583ab1f77daa4..c61b6022575e1abe24a4a7bbf67729a0ad140315 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -65,6 +65,7 @@ #define SDMA_DESCQ_CNT 2048 #define SDMA_DESC_INTR 64 #define INVALID_TAIL 0xffff +#define SDMA_PAD max_t(size_t, MAX_16B_PADDING, sizeof(u32)) static uint sdma_descq_cnt = SDMA_DESCQ_CNT; module_param(sdma_descq_cnt, uint, S_IRUGO); @@ -1296,7 +1297,7 @@ void sdma_clean(struct hfi1_devdata *dd, size_t num_engines) struct sdma_engine *sde; if (dd->sdma_pad_dma) { - dma_free_coherent(&dd->pcidev->dev, 4, + dma_free_coherent(&dd->pcidev->dev, SDMA_PAD, (void *)dd->sdma_pad_dma, dd->sdma_pad_phys); dd->sdma_pad_dma = NULL; @@ -1491,7 +1492,7 @@ int sdma_init(struct hfi1_devdata *dd, u8 port) } /* Allocate memory for pad */ - dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, sizeof(u32), + dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, SDMA_PAD, &dd->sdma_pad_phys, GFP_KERNEL); if (!dd->sdma_pad_dma) { dd_dev_err(dd, "failed to allocate SendDMA pad memory\n"); diff --git a/drivers/infiniband/hw/hfi1/tid_rdma.c b/drivers/infiniband/hw/hfi1/tid_rdma.c index b4dcc4d29f84e0e10fcd312b97b520fda0507fd8..f21fca3617d5feae86f97213130c84426efb3218 100644 --- a/drivers/infiniband/hw/hfi1/tid_rdma.c +++ b/drivers/infiniband/hw/hfi1/tid_rdma.c @@ -2736,11 +2736,6 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd, diff = cmp_psn(psn, flow->flow_state.r_next_psn); if (diff > 0) { - if (!(qp->r_flags & RVT_R_RDMAR_SEQ)) - restart_tid_rdma_read_req(rcd, - qp, - wqe); - /* Drop the packet.*/ goto s_unlock; } else if (diff < 0) { diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 7bff0a1e713d77535a1ba52de3186b082b1e429e..089e201d75500072f527410a6ea8b1499fef19b1 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -147,9 +147,6 @@ static int pio_wait(struct rvt_qp *qp, /* Length of buffer to create verbs txreq cache name */ #define TXREQ_NAME_LEN 24 -/* 16B trailing buffer */ -static const u8 trail_buf[MAX_16B_PADDING]; - static uint wss_threshold = 80; module_param(wss_threshold, uint, S_IRUGO); MODULE_PARM_DESC(wss_threshold, "Percentage (1-100) of LLC to use as a threshold for a cacheless copy"); @@ -820,8 +817,8 @@ static int build_verbs_tx_desc( /* add icrc, lt byte, and padding to flit */ if (extra_bytes) - ret = sdma_txadd_kvaddr(sde->dd, &tx->txreq, - (void *)trail_buf, extra_bytes); + ret = sdma_txadd_daddr(sde->dd, &tx->txreq, + sde->dd->sdma_pad_phys, extra_bytes); bail_txadd: return ret; @@ -1089,7 +1086,8 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps, } /* add icrc, lt byte, and padding to flit */ if (extra_bytes) - seg_pio_copy_mid(pbuf, trail_buf, extra_bytes); + seg_pio_copy_mid(pbuf, ppd->dd->sdma_pad_dma, + extra_bytes); seg_pio_copy_end(pbuf); } diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 7a89d669f8bfa93265228c855d233a48cd5f5cf6..e82567fcdeb7f05c46110a77176d50563ee3e10f 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -5389,9 +5389,9 @@ static void hns_roce_v2_free_eq(struct hns_roce_dev *hr_dev, return; } - if (eq->buf_list) - dma_free_coherent(hr_dev->dev, buf_chk_sz, - eq->buf_list->buf, eq->buf_list->map); + dma_free_coherent(hr_dev->dev, buf_chk_sz, eq->buf_list->buf, + eq->buf_list->map); + kfree(eq->buf_list); } static void hns_roce_config_eqc(struct hns_roce_dev *hr_dev, diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index 630599311586ec23491025dac5603da7d848ead7..7019c12005f4c1fb0606473b0ef72b50af7c3af5 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c @@ -1967,8 +1967,8 @@ int mlx5_ib_dealloc_mw(struct ib_mw *mw) int err; if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) { - xa_erase(&dev->mdev->priv.mkey_table, - mlx5_base_mkey(mmw->mmkey.key)); + xa_erase_irq(&dev->mdev->priv.mkey_table, + mlx5_base_mkey(mmw->mmkey.key)); /* * pagefault_single_data_segment() may be accessing mmw under * SRCU if the user bound an ODP MR to this MW. diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 8937d72ddcf6bdb44f48b37acbbec178fa2650e0..5fd071c05944d900b95654925dfff09bc47e1e69 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -3249,10 +3249,12 @@ static int modify_raw_packet_qp_sq( } /* Only remove the old rate after new rate was set */ - if ((old_rl.rate && - !mlx5_rl_are_equal(&old_rl, &new_rl)) || - (new_state != MLX5_SQC_STATE_RDY)) + if ((old_rl.rate && !mlx5_rl_are_equal(&old_rl, &new_rl)) || + (new_state != MLX5_SQC_STATE_RDY)) { mlx5_rl_remove_rate(dev, &old_rl); + if (new_state != MLX5_SQC_STATE_RDY) + memset(&new_rl, 0, sizeof(new_rl)); + } ibqp->rl = new_rl; sq->state = new_state; diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c index 5136b835e1ba0521050caf388d018125a0ad2347..dc71b6e16a07f300306a2d39b255d546ac3a38ea 100644 --- a/drivers/infiniband/hw/qedr/main.c +++ b/drivers/infiniband/hw/qedr/main.c @@ -76,7 +76,7 @@ static void qedr_get_dev_fw_str(struct ib_device *ibdev, char *str) struct qedr_dev *qedr = get_qedr_dev(ibdev); u32 fw_ver = (u32)qedr->attr.fw_ver; - snprintf(str, IB_FW_VERSION_NAME_MAX, "%d. %d. %d. %d", + snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%d.%d", (fw_ver >> 24) & 0xFF, (fw_ver >> 16) & 0xFF, (fw_ver >> 8) & 0xFF, fw_ver & 0xFF); } diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c index 52d402f39df93c28771d09ee9b673ea40303101f..b4317480cee7486d2f461d4b870cd801bc636d93 100644 --- a/drivers/infiniband/sw/siw/siw_qp.c +++ b/drivers/infiniband/sw/siw/siw_qp.c @@ -1312,6 +1312,7 @@ int siw_qp_add(struct siw_device *sdev, struct siw_qp *qp) void siw_free_qp(struct kref *ref) { struct siw_qp *found, *qp = container_of(ref, struct siw_qp, ref); + struct siw_base_qp *siw_base_qp = to_siw_base_qp(qp->ib_qp); struct siw_device *sdev = qp->sdev; unsigned long flags; @@ -1334,4 +1335,5 @@ void siw_free_qp(struct kref *ref) atomic_dec(&sdev->num_qp); siw_dbg_qp(qp, "free QP\n"); kfree_rcu(qp, rcu); + kfree(siw_base_qp); } diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c index 869e02b69a012389d6d3533241012b1c1309e401..b18a677832e105ded578bd74d29694c45e55d031 100644 --- a/drivers/infiniband/sw/siw/siw_verbs.c +++ b/drivers/infiniband/sw/siw/siw_verbs.c @@ -604,7 +604,6 @@ int siw_verbs_modify_qp(struct ib_qp *base_qp, struct ib_qp_attr *attr, int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata) { struct siw_qp *qp = to_siw_qp(base_qp); - struct siw_base_qp *siw_base_qp = to_siw_base_qp(base_qp); struct siw_ucontext *uctx = rdma_udata_to_drv_context(udata, struct siw_ucontext, base_ucontext); @@ -641,7 +640,6 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata) qp->scq = qp->rcq = NULL; siw_qp_put(qp); - kfree(siw_base_qp); return 0; } diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c index dace8577fa43dcf1f84843bfeeda123e96b952fb..79851923ee576ab59d28d2f764b30d6b6a4b2f67 100644 --- a/drivers/input/misc/da9063_onkey.c +++ b/drivers/input/misc/da9063_onkey.c @@ -232,10 +232,7 @@ static int da9063_onkey_probe(struct platform_device *pdev) onkey->input->phys = onkey->phys; onkey->input->dev.parent = &pdev->dev; - if (onkey->key_power) - input_set_capability(onkey->input, EV_KEY, KEY_POWER); - - input_set_capability(onkey->input, EV_KEY, KEY_SLEEP); + input_set_capability(onkey->input, EV_KEY, KEY_POWER); INIT_DELAYED_WORK(&onkey->work, da9063_poll_on); diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 97e3639e99d0cdbeee8c5482e1b1d353e67d9441..08520b3a18b88d3e463e9ea7dd84c07f3567ed8a 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -92,11 +92,18 @@ soc_button_device_create(struct platform_device *pdev, continue; gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index); - if (gpio < 0 && gpio != -ENOENT) { - error = gpio; - goto err_free_mem; - } else if (!gpio_is_valid(gpio)) { - /* Skip GPIO if not present */ + if (!gpio_is_valid(gpio)) { + /* + * Skip GPIO if not present. Note we deliberately + * ignore -EPROBE_DEFER errors here. On some devices + * Intel is using so called virtual GPIOs which are not + * GPIOs at all but some way for AML code to check some + * random status bits without need a custom opregion. + * In some cases the resources table we parse points to + * such a virtual GPIO, since these are not real GPIOs + * we do not have a driver for these so they will never + * show up, therefore we ignore -EPROBE_DEFER. + */ continue; } diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 04fe43440a3c8740d58ee1cb944fc3b7099aa981..2d8434b7b62381a85abdb28daba2391fdd117e40 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1827,31 +1827,6 @@ static int elantech_create_smbus(struct psmouse *psmouse, leave_breadcrumbs); } -static bool elantech_use_host_notify(struct psmouse *psmouse, - struct elantech_device_info *info) -{ - if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version)) - return true; - - switch (info->bus) { - case ETP_BUS_PS2_ONLY: - /* expected case */ - break; - case ETP_BUS_SMB_HST_NTFY_ONLY: - case ETP_BUS_PS2_SMB_HST_NTFY: - /* SMbus implementation is stable since 2018 */ - if (dmi_get_bios_year() >= 2018) - return true; - /* fall through */ - default: - psmouse_dbg(psmouse, - "Ignoring SMBus bus provider %d\n", info->bus); - break; - } - - return false; -} - /** * elantech_setup_smbus - called once the PS/2 devices are enumerated * and decides to instantiate a SMBus InterTouch device. @@ -1871,7 +1846,7 @@ static int elantech_setup_smbus(struct psmouse *psmouse, * i2c_blacklist_pnp_ids. * Old ICs are up to the user to decide. */ - if (!elantech_use_host_notify(psmouse, info) || + if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) || psmouse_matches_pnp_id(psmouse, i2c_blacklist_pnp_ids)) return -ENXIO; } @@ -1891,6 +1866,34 @@ static int elantech_setup_smbus(struct psmouse *psmouse, return 0; } +static bool elantech_use_host_notify(struct psmouse *psmouse, + struct elantech_device_info *info) +{ + if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version)) + return true; + + switch (info->bus) { + case ETP_BUS_PS2_ONLY: + /* expected case */ + break; + case ETP_BUS_SMB_ALERT_ONLY: + /* fall-through */ + case ETP_BUS_PS2_SMB_ALERT: + psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n"); + break; + case ETP_BUS_SMB_HST_NTFY_ONLY: + /* fall-through */ + case ETP_BUS_PS2_SMB_HST_NTFY: + return true; + default: + psmouse_dbg(psmouse, + "Ignoring SMBus bus provider %d.\n", + info->bus); + } + + return false; +} + int elantech_init_smbus(struct psmouse *psmouse) { struct elantech_device_info info; diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index 772493b1f665da7bad6c857902a2bfbb00d12c5e..190b9974526bb9e78f8b3200283b680690db2079 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -146,7 +146,7 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev) } mutex_lock(&data->irq_mutex); - bitmap_and(data->irq_status, data->irq_status, data->current_irq_mask, + bitmap_and(data->irq_status, data->irq_status, data->fn_irq_bits, data->irq_count); /* * At this point, irq_status has all bits that are set in the @@ -385,6 +385,8 @@ static int rmi_driver_set_irq_bits(struct rmi_device *rmi_dev, bitmap_copy(data->current_irq_mask, data->new_irq_mask, data->num_of_irq_regs); + bitmap_or(data->fn_irq_bits, data->fn_irq_bits, mask, data->irq_count); + error_unlock: mutex_unlock(&data->irq_mutex); return error; @@ -398,6 +400,8 @@ static int rmi_driver_clear_irq_bits(struct rmi_device *rmi_dev, struct device *dev = &rmi_dev->dev; mutex_lock(&data->irq_mutex); + bitmap_andnot(data->fn_irq_bits, + data->fn_irq_bits, mask, data->irq_count); bitmap_andnot(data->new_irq_mask, data->current_irq_mask, mask, data->irq_count); diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 5178ea8b5f3099eee52a8483e72fa0b2dcce679b..fb43aa708660632613013c936b937bfe9991f46e 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -53,6 +53,7 @@ struct goodix_ts_data { const char *cfg_name; struct completion firmware_loading_complete; unsigned long irq_flags; + unsigned int contact_size; }; #define GOODIX_GPIO_INT_NAME "irq" @@ -62,6 +63,7 @@ struct goodix_ts_data { #define GOODIX_MAX_WIDTH 4096 #define GOODIX_INT_TRIGGER 1 #define GOODIX_CONTACT_SIZE 8 +#define GOODIX_MAX_CONTACT_SIZE 9 #define GOODIX_MAX_CONTACTS 10 #define GOODIX_CONFIG_MAX_LENGTH 240 @@ -144,6 +146,19 @@ static const struct dmi_system_id rotated_screen[] = { {} }; +static const struct dmi_system_id nine_bytes_report[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + .ident = "Lenovo YogaBook", + /* YB1-X91L/F and YB1-X90L/F */ + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9") + } + }, +#endif + {} +}; + /** * goodix_i2c_read - read data from a register of the i2c slave device. * @@ -249,7 +264,7 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) max_timeout = jiffies + msecs_to_jiffies(GOODIX_BUFFER_STATUS_TIMEOUT); do { error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, - data, GOODIX_CONTACT_SIZE + 1); + data, ts->contact_size + 1); if (error) { dev_err(&ts->client->dev, "I2C transfer error: %d\n", error); @@ -262,12 +277,12 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) return -EPROTO; if (touch_num > 1) { - data += 1 + GOODIX_CONTACT_SIZE; + data += 1 + ts->contact_size; error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR + - 1 + GOODIX_CONTACT_SIZE, + 1 + ts->contact_size, data, - GOODIX_CONTACT_SIZE * + ts->contact_size * (touch_num - 1)); if (error) return error; @@ -286,7 +301,7 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) return 0; } -static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) +static void goodix_ts_report_touch_8b(struct goodix_ts_data *ts, u8 *coor_data) { int id = coor_data[0] & 0x0F; int input_x = get_unaligned_le16(&coor_data[1]); @@ -301,6 +316,21 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w); } +static void goodix_ts_report_touch_9b(struct goodix_ts_data *ts, u8 *coor_data) +{ + int id = coor_data[1] & 0x0F; + int input_x = get_unaligned_le16(&coor_data[3]); + int input_y = get_unaligned_le16(&coor_data[5]); + int input_w = get_unaligned_le16(&coor_data[7]); + + input_mt_slot(ts->input_dev, id); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); + touchscreen_report_pos(ts->input_dev, &ts->prop, + input_x, input_y, true); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w); +} + /** * goodix_process_events - Process incoming events * @@ -311,7 +341,7 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) */ static void goodix_process_events(struct goodix_ts_data *ts) { - u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS]; + u8 point_data[1 + GOODIX_MAX_CONTACT_SIZE * GOODIX_MAX_CONTACTS]; int touch_num; int i; @@ -326,8 +356,12 @@ static void goodix_process_events(struct goodix_ts_data *ts) input_report_key(ts->input_dev, KEY_LEFTMETA, point_data[0] & BIT(4)); for (i = 0; i < touch_num; i++) - goodix_ts_report_touch(ts, - &point_data[1 + GOODIX_CONTACT_SIZE * i]); + if (ts->contact_size == 9) + goodix_ts_report_touch_9b(ts, + &point_data[1 + ts->contact_size * i]); + else + goodix_ts_report_touch_8b(ts, + &point_data[1 + ts->contact_size * i]); input_mt_sync_frame(ts->input_dev); input_sync(ts->input_dev); @@ -730,6 +764,13 @@ static int goodix_configure_dev(struct goodix_ts_data *ts) "Applying '180 degrees rotated screen' quirk\n"); } + if (dmi_check_system(nine_bytes_report)) { + ts->contact_size = 9; + + dev_dbg(&ts->client->dev, + "Non-standard 9-bytes report format quirk\n"); + } + error = input_mt_init_slots(ts->input_dev, ts->max_touch_num, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); if (error) { @@ -810,6 +851,7 @@ static int goodix_ts_probe(struct i2c_client *client, ts->client = client; i2c_set_clientdata(client, ts); init_completion(&ts->firmware_loading_complete); + ts->contact_size = GOODIX_CONTACT_SIZE; error = goodix_get_gpio_config(ts); if (error) diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 34923399ece4e98534022f90d8ad4180ef4536b6..1139714e72e2672f26a52be85280e7f8fea22e11 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -81,8 +81,10 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts) for (i = 0, y = 0; i < ts->chip_info->max_fingers; i++, y += 3) { finger[i].is_valid = buf[i + y] >> 7; if (finger[i].is_valid) { - finger[i].x = ((buf[i + y] & 0x0070) << 4) | buf[i + 1]; - finger[i].y = ((buf[i + y] & 0x0007) << 8) | buf[i + 2]; + finger[i].x = ((buf[i + y] & 0x0070) << 4) | + buf[i + y + 1]; + finger[i].y = ((buf[i + y] & 0x0007) << 8) | + buf[i + y + 2]; /* st1232 includes a z-axis / touch strength */ if (ts->chip_info->have_z) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 2369b8af81f3b7e4d829a75ef979fb1858f0682f..dd555078258c437c375902538ecc2f9040efd7cc 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -583,7 +583,8 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) retry: type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; - pasid = PPR_PASID(*(u64 *)&event[0]); + pasid = (event[0] & EVENT_DOMID_MASK_HI) | + (event[1] & EVENT_DOMID_MASK_LO); flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; address = (u64)(((u64)event[3]) << 32) | event[2]; @@ -616,7 +617,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) address, flags); break; case EVENT_TYPE_PAGE_TAB_ERR: - dev_err(dev, "Event logged [PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x domain=0x%04x address=0x%llx flags=0x%04x]\n", + dev_err(dev, "Event logged [PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x pasid=0x%04x address=0x%llx flags=0x%04x]\n", PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), pasid, address, flags); break; @@ -1463,6 +1464,7 @@ static void free_pagetable(struct protection_domain *domain) * to 64 bits. */ static bool increase_address_space(struct protection_domain *domain, + unsigned long address, gfp_t gfp) { unsigned long flags; @@ -1471,8 +1473,8 @@ static bool increase_address_space(struct protection_domain *domain, spin_lock_irqsave(&domain->lock, flags); - if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL)) - /* address space already 64 bit large */ + if (address <= PM_LEVEL_SIZE(domain->mode) || + WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL)) goto out; pte = (void *)get_zeroed_page(gfp); @@ -1505,7 +1507,7 @@ static u64 *alloc_pte(struct protection_domain *domain, BUG_ON(!is_power_of_2(page_size)); while (address > PM_LEVEL_SIZE(domain->mode)) - *updated = increase_address_space(domain, gfp) || *updated; + *updated = increase_address_space(domain, address, gfp) || *updated; level = domain->mode - 1; pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; diff --git a/drivers/iommu/amd_iommu_quirks.c b/drivers/iommu/amd_iommu_quirks.c index c235f79b7a200c90f8b8d4325a61ce4373de8d86..5120ce4fdce326b6b59185d66e7ba8cb146bf4d5 100644 --- a/drivers/iommu/amd_iommu_quirks.c +++ b/drivers/iommu/amd_iommu_quirks.c @@ -73,6 +73,19 @@ static const struct dmi_system_id ivrs_quirks[] __initconst = { }, .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495], }, + { + /* + * Acer Aspire A315-41 requires the very same workaround as + * Dell Latitude 5495 + */ + .callback = ivrs_ioapic_quirk_cb, + .ident = "Acer Aspire A315-41", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-41"), + }, + .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495], + }, { .callback = ivrs_ioapic_quirk_cb, .ident = "Lenovo ideapad 330S-15ARR", diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index c9c1612d52e00090a2fb1a4e374e9468ba25607e..17bd5a349119f89d7ba2f140fc89d99ed73e85d4 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -130,8 +130,8 @@ #define EVENT_TYPE_INV_PPR_REQ 0x9 #define EVENT_DEVID_MASK 0xffff #define EVENT_DEVID_SHIFT 0 -#define EVENT_DOMID_MASK 0xffff -#define EVENT_DOMID_SHIFT 0 +#define EVENT_DOMID_MASK_LO 0xffff +#define EVENT_DOMID_MASK_HI 0xf0000 #define EVENT_FLAGS_MASK 0xfff #define EVENT_FLAGS_SHIFT 0x10 diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 3f974919d3bdb4c7ee78adc091f585c4cc7a6da7..6db6d969e31c6adcc5202fa0ea97eabf347b7b63 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2794,7 +2794,7 @@ static int identity_mapping(struct device *dev) struct device_domain_info *info; info = dev->archdata.iommu; - if (info && info != DUMMY_DEVICE_DOMAIN_INFO) + if (info && info != DUMMY_DEVICE_DOMAIN_INFO && info != DEFER_DEVICE_DOMAIN_INFO) return (info->domain == si_domain); return 0; @@ -3471,7 +3471,7 @@ static bool iommu_need_mapping(struct device *dev) if (dev->coherent_dma_mask && dev->coherent_dma_mask < dma_mask) dma_mask = dev->coherent_dma_mask; - if (dma_mask >= dma_get_required_mask(dev)) + if (dma_mask >= dma_direct_get_required_mask(dev)) return false; /* @@ -3775,6 +3775,13 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele return nelems; } +static u64 intel_get_required_mask(struct device *dev) +{ + if (!iommu_need_mapping(dev)) + return dma_direct_get_required_mask(dev); + return DMA_BIT_MASK(32); +} + static const struct dma_map_ops intel_dma_ops = { .alloc = intel_alloc_coherent, .free = intel_free_coherent, @@ -3787,6 +3794,7 @@ static const struct dma_map_ops intel_dma_ops = { .dma_supported = dma_direct_supported, .mmap = dma_common_mmap, .get_sgtable = dma_common_get_sgtable, + .get_required_mask = intel_get_required_mask, }; static void diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index f676bbc3eec3d1059bf910a5c8b0d2ba969da6ba..97338efb30119f36028d6884fdf63fc5880c1c36 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -176,6 +176,9 @@ #define ARM_MALI_LPAE_TTBR_READ_INNER BIT(2) #define ARM_MALI_LPAE_TTBR_SHARE_OUTER BIT(4) +#define ARM_MALI_LPAE_MEMATTR_IMP_DEF 0x88ULL +#define ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC 0x8DULL + /* IOPTE accessors */ #define iopte_deref(pte, d) \ (__va(iopte_val(pte) & ((1ULL << ARM_LPAE_MAX_ADDR_BITS) - 1) \ @@ -1372,27 +1375,57 @@ arm_32_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie) static struct io_pgtable * arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) { - struct io_pgtable *iop; + struct arm_lpae_io_pgtable *data; - if (cfg->ias != 48 || cfg->oas > 40) + /* No quirks for Mali (hopefully) */ + if (cfg->quirks) + return NULL; + + if (cfg->ias > 48 || cfg->oas > 40) return NULL; cfg->pgsize_bitmap &= (SZ_4K | SZ_2M | SZ_1G); - iop = arm_64_lpae_alloc_pgtable_s1(cfg, cookie); - if (iop) { - u64 mair, ttbr; - /* Copy values as union fields overlap */ - mair = cfg->arm_lpae_s1_cfg.mair[0]; - ttbr = cfg->arm_lpae_s1_cfg.ttbr[0]; + data = arm_lpae_alloc_pgtable(cfg); + if (!data) + return NULL; - cfg->arm_mali_lpae_cfg.memattr = mair; - cfg->arm_mali_lpae_cfg.transtab = ttbr | - ARM_MALI_LPAE_TTBR_READ_INNER | - ARM_MALI_LPAE_TTBR_ADRMODE_TABLE; + /* Mali seems to need a full 4-level table regardless of IAS */ + if (data->levels < ARM_LPAE_MAX_LEVELS) { + data->levels = ARM_LPAE_MAX_LEVELS; + data->pgd_size = sizeof(arm_lpae_iopte); } + /* + * MEMATTR: Mali has no actual notion of a non-cacheable type, so the + * best we can do is mimic the out-of-tree driver and hope that the + * "implementation-defined caching policy" is good enough. Similarly, + * we'll use it for the sake of a valid attribute for our 'device' + * index, although callers should never request that in practice. + */ + cfg->arm_mali_lpae_cfg.memattr = + (ARM_MALI_LPAE_MEMATTR_IMP_DEF + << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_NC)) | + (ARM_MALI_LPAE_MEMATTR_WRITE_ALLOC + << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) | + (ARM_MALI_LPAE_MEMATTR_IMP_DEF + << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_DEV)); - return iop; + data->pgd = __arm_lpae_alloc_pages(data->pgd_size, GFP_KERNEL, + cfg, cookie); + if (!data->pgd) + goto out_free_data; + + /* Ensure the empty pgd is visible before TRANSTAB can be written */ + wmb(); + + cfg->arm_mali_lpae_cfg.transtab = virt_to_phys(data->pgd) | + ARM_MALI_LPAE_TTBR_READ_INNER | + ARM_MALI_LPAE_TTBR_ADRMODE_TABLE; + return &data->iop; + +out_free_data: + kfree(data); + return NULL; } struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = { diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c index e436ff813e7e5bcced5225a11a6a25baa2bb5814..7af76473b3e3b7fb3c8d145d18aaf17c5e0b1fcb 100644 --- a/drivers/iommu/iommu-sysfs.c +++ b/drivers/iommu/iommu-sysfs.c @@ -87,6 +87,7 @@ int iommu_device_sysfs_add(struct iommu_device *iommu, put_device(iommu->dev); return ret; } +EXPORT_SYMBOL_GPL(iommu_device_sysfs_add); void iommu_device_sysfs_remove(struct iommu_device *iommu) { @@ -119,6 +120,7 @@ int iommu_device_link(struct iommu_device *iommu, struct device *link) return ret; } +EXPORT_SYMBOL_GPL(iommu_device_link); void iommu_device_unlink(struct iommu_device *iommu, struct device *link) { @@ -128,3 +130,4 @@ void iommu_device_unlink(struct iommu_device *iommu, struct device *link) sysfs_remove_link(&link->kobj, "iommu"); sysfs_remove_link_from_group(&iommu->dev->kobj, "devices", dev_name(link)); } +EXPORT_SYMBOL_GPL(iommu_device_unlink); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 64a8bd2abc5d27250b2c0c7e45919a34b22e3312..0346ee7bd768bace0978f3c6c4fff4e916e30c27 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -144,6 +144,7 @@ int iommu_device_register(struct iommu_device *iommu) spin_unlock(&iommu_device_lock); return 0; } +EXPORT_SYMBOL_GPL(iommu_device_register); void iommu_device_unregister(struct iommu_device *iommu) { @@ -889,6 +890,7 @@ struct iommu_group *iommu_group_ref_get(struct iommu_group *group) kobject_get(group->devices_kobj); return group; } +EXPORT_SYMBOL_GPL(iommu_group_ref_get); /** * iommu_group_put - Decrement group reference @@ -1262,6 +1264,7 @@ struct iommu_group *generic_device_group(struct device *dev) { return iommu_group_alloc(); } +EXPORT_SYMBOL_GPL(generic_device_group); /* * Use standard PCI bus topology, isolation features, and DMA alias quirks @@ -1329,6 +1332,7 @@ struct iommu_group *pci_device_group(struct device *dev) /* No shared group found, allocate new */ return iommu_group_alloc(); } +EXPORT_SYMBOL_GPL(pci_device_group); /* Get the IOMMU group for device on fsl-mc bus */ struct iommu_group *fsl_mc_device_group(struct device *dev) @@ -1409,6 +1413,7 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev) return group; } +EXPORT_SYMBOL_GPL(iommu_group_get_for_dev); struct iommu_domain *iommu_group_default_domain(struct iommu_group *group) { @@ -2248,6 +2253,7 @@ struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start, region->type = type; return region; } +EXPORT_SYMBOL_GPL(iommu_alloc_resv_region); static int request_default_domain_for_dev(struct device *dev, unsigned long type) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 9da8309f71708f213f91dbe99374681e0da3f652..2639fc7181171c4ab1db52bb0765c8f0a8b24bd6 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -1086,8 +1086,6 @@ static int ipmmu_probe(struct platform_device *pdev) mmu->num_ctx = min(IPMMU_CTX_MAX, mmu->features->number_of_contexts); - irq = platform_get_irq(pdev, 0); - /* * Determine if this IPMMU instance is a root device by checking for * the lack of has_cache_leaf_nodes flag or renesas,ipmmu-main property. @@ -1106,10 +1104,9 @@ static int ipmmu_probe(struct platform_device *pdev) /* Root devices have mandatory IRQs */ if (ipmmu_is_root(mmu)) { - if (irq < 0) { - dev_err(&pdev->dev, "no IRQ found\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, ipmmu_irq, 0, dev_name(&pdev->dev), mmu); diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 26290f310f90bd8c6d05da9b255ec02d144cd56f..4dcbf68dfda436828ded5d86442d19e48fa62ff1 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -100,6 +100,7 @@ struct rk_iommu { struct device *dev; void __iomem **bases; int num_mmu; + int num_irq; struct clk_bulk_data *clocks; int num_clocks; bool reset_disabled; @@ -1136,7 +1137,7 @@ static int rk_iommu_probe(struct platform_device *pdev) struct rk_iommu *iommu; struct resource *res; int num_res = pdev->num_resources; - int err, i, irq; + int err, i; iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL); if (!iommu) @@ -1163,6 +1164,10 @@ static int rk_iommu_probe(struct platform_device *pdev) if (iommu->num_mmu == 0) return PTR_ERR(iommu->bases[0]); + iommu->num_irq = platform_irq_count(pdev); + if (iommu->num_irq < 0) + return iommu->num_irq; + iommu->reset_disabled = device_property_read_bool(dev, "rockchip,disable-mmu-reset"); @@ -1219,8 +1224,9 @@ static int rk_iommu_probe(struct platform_device *pdev) pm_runtime_enable(dev); - i = 0; - while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) { + for (i = 0; i < iommu->num_irq; i++) { + int irq = platform_get_irq(pdev, i); + if (irq < 0) return irq; @@ -1245,10 +1251,13 @@ static int rk_iommu_probe(struct platform_device *pdev) static void rk_iommu_shutdown(struct platform_device *pdev) { struct rk_iommu *iommu = platform_get_drvdata(pdev); - int i = 0, irq; + int i; + + for (i = 0; i < iommu->num_irq; i++) { + int irq = platform_get_irq(pdev, i); - while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) devm_free_irq(iommu->dev, irq, iommu); + } pm_runtime_force_suspend(&pdev->dev); } diff --git a/drivers/irqchip/irq-al-fic.c b/drivers/irqchip/irq-al-fic.c index 1a57cee3efab165591d3933ebda9711164e2c51c..0b0a737397562472636525b88a1fd3559b6dafc2 100644 --- a/drivers/irqchip/irq-al-fic.c +++ b/drivers/irqchip/irq-al-fic.c @@ -15,6 +15,7 @@ /* FIC Registers */ #define AL_FIC_CAUSE 0x00 +#define AL_FIC_SET_CAUSE 0x08 #define AL_FIC_MASK 0x10 #define AL_FIC_CONTROL 0x28 @@ -126,6 +127,16 @@ static void al_fic_irq_handler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } +static int al_fic_irq_retrigger(struct irq_data *data) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); + struct al_fic *fic = gc->private; + + writel_relaxed(BIT(data->hwirq), fic->base + AL_FIC_SET_CAUSE); + + return 1; +} + static int al_fic_register(struct device_node *node, struct al_fic *fic) { @@ -159,6 +170,7 @@ static int al_fic_register(struct device_node *node, gc->chip_types->chip.irq_unmask = irq_gc_mask_clr_bit; gc->chip_types->chip.irq_ack = irq_gc_ack_clr_bit; gc->chip_types->chip.irq_set_type = al_fic_irq_set_type; + gc->chip_types->chip.irq_retrigger = al_fic_irq_retrigger; gc->chip_types->chip.flags = IRQCHIP_SKIP_SET_WAKE; gc->private = fic; diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c index 6acad2ea0fb3565a2604ecbb3fb5235395d62fad..29333497ba10d2707e430e333e0c7d85e132d3ad 100644 --- a/drivers/irqchip/irq-atmel-aic5.c +++ b/drivers/irqchip/irq-atmel-aic5.c @@ -313,6 +313,7 @@ static void __init sama5d3_aic_irq_fixup(void) static const struct of_device_id aic5_irq_fixups[] __initconst = { { .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup }, { .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup }, + { .compatible = "microchip,sam9x60", .data = sama5d3_aic_irq_fixup }, { /* sentinel */ }, }; @@ -390,3 +391,12 @@ static int __init sama5d4_aic5_of_init(struct device_node *node, return aic5_of_init(node, parent, NR_SAMA5D4_IRQS); } IRQCHIP_DECLARE(sama5d4_aic5, "atmel,sama5d4-aic", sama5d4_aic5_of_init); + +#define NR_SAM9X60_IRQS 50 + +static int __init sam9x60_aic5_of_init(struct device_node *node, + struct device_node *parent) +{ + return aic5_of_init(node, parent, NR_SAM9X60_IRQS); +} +IRQCHIP_DECLARE(sam9x60_aic5, "microchip,sam9x60-aic", sam9x60_aic5_of_init); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 62e54f1a248ba002942bc0bae0c6b97d52f9f857..787e8eec9a7f1862275587f079d2809715baeeec 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -175,6 +175,22 @@ static DEFINE_IDA(its_vpeid_ida); #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) +static u16 get_its_list(struct its_vm *vm) +{ + struct its_node *its; + unsigned long its_list = 0; + + list_for_each_entry(its, &its_nodes, entry) { + if (!its->is_v4) + continue; + + if (vm->vlpi_count[its->list_nr]) + __set_bit(its->list_nr, &its_list); + } + + return (u16)its_list; +} + static struct its_collection *dev_event_to_col(struct its_device *its_dev, u32 event) { @@ -976,17 +992,15 @@ static void its_send_vmapp(struct its_node *its, static void its_send_vmovp(struct its_vpe *vpe) { - struct its_cmd_desc desc; + struct its_cmd_desc desc = {}; struct its_node *its; unsigned long flags; int col_id = vpe->col_idx; desc.its_vmovp_cmd.vpe = vpe; - desc.its_vmovp_cmd.its_list = (u16)its_list_map; if (!its_list_map) { its = list_first_entry(&its_nodes, struct its_node, entry); - desc.its_vmovp_cmd.seq_num = 0; desc.its_vmovp_cmd.col = &its->collections[col_id]; its_send_single_vcommand(its, its_build_vmovp_cmd, &desc); return; @@ -1003,6 +1017,7 @@ static void its_send_vmovp(struct its_vpe *vpe) raw_spin_lock_irqsave(&vmovp_lock, flags); desc.its_vmovp_cmd.seq_num = vmovp_seq_num++; + desc.its_vmovp_cmd.its_list = get_its_list(vpe->its_vm); /* Emit VMOVPs */ list_for_each_entry(its, &its_nodes, entry) { diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index ee350b08f846d92c5fc69cf9b63891879e261323..67101fc877c82ec008af8f71d3d78db11cae5bdf 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -62,7 +62,7 @@ static struct gic_chip_data gic_data __read_mostly; static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key); #define GIC_ID_NR (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer)) -#define GIC_LINE_NR max(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U) +#define GIC_LINE_NR min(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U) #define GIC_ESPI_NR GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer) /* diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c index c72c036aea768001a19d5d702f490f005f6636cd..7d0a12fe2714a72979cf56281be5a78fa644064a 100644 --- a/drivers/irqchip/irq-sifive-plic.c +++ b/drivers/irqchip/irq-sifive-plic.c @@ -97,7 +97,7 @@ static inline void plic_irq_toggle(const struct cpumask *mask, } } -static void plic_irq_enable(struct irq_data *d) +static void plic_irq_unmask(struct irq_data *d) { unsigned int cpu = cpumask_any_and(irq_data_get_affinity_mask(d), cpu_online_mask); @@ -106,7 +106,7 @@ static void plic_irq_enable(struct irq_data *d) plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1); } -static void plic_irq_disable(struct irq_data *d) +static void plic_irq_mask(struct irq_data *d) { plic_irq_toggle(cpu_possible_mask, d->hwirq, 0); } @@ -125,10 +125,8 @@ static int plic_set_affinity(struct irq_data *d, if (cpu >= nr_cpu_ids) return -EINVAL; - if (!irqd_irq_disabled(d)) { - plic_irq_toggle(cpu_possible_mask, d->hwirq, 0); - plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1); - } + plic_irq_toggle(cpu_possible_mask, d->hwirq, 0); + plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1); irq_data_update_effective_affinity(d, cpumask_of(cpu)); @@ -136,14 +134,18 @@ static int plic_set_affinity(struct irq_data *d, } #endif +static void plic_irq_eoi(struct irq_data *d) +{ + struct plic_handler *handler = this_cpu_ptr(&plic_handlers); + + writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); +} + static struct irq_chip plic_chip = { .name = "SiFive PLIC", - /* - * There is no need to mask/unmask PLIC interrupts. They are "masked" - * by reading claim and "unmasked" when writing it back. - */ - .irq_enable = plic_irq_enable, - .irq_disable = plic_irq_disable, + .irq_mask = plic_irq_mask, + .irq_unmask = plic_irq_unmask, + .irq_eoi = plic_irq_eoi, #ifdef CONFIG_SMP .irq_set_affinity = plic_set_affinity, #endif @@ -152,7 +154,7 @@ static struct irq_chip plic_chip = { static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { - irq_set_chip_and_handler(irq, &plic_chip, handle_simple_irq); + irq_set_chip_and_handler(irq, &plic_chip, handle_fasteoi_irq); irq_set_chip_data(irq, NULL); irq_set_noprobe(irq); return 0; @@ -188,7 +190,6 @@ static void plic_handle_irq(struct pt_regs *regs) hwirq); else generic_handle_irq(irq); - writel(hwirq, claim); } csr_set(sie, SIE_SEIE); } @@ -251,8 +252,8 @@ static int __init plic_init(struct device_node *node, continue; } - /* skip context holes */ - if (parent.args[0] == -1) + /* skip contexts other than supervisor external interrupt */ + if (parent.args[0] != IRQ_S_EXT) continue; hartid = plic_find_hart_id(parent.np); diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index 5d5983cb48e5978b10b1b1f64a412cb81eb77ef0..dc89a13a7901ba9c6cb9dd23ff531082132716d3 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -25,6 +25,8 @@ #define PDC_MAX_IRQS 168 #define PDC_IPC_LOG_SZ 2 + +#define PDC_MAX_IRQS 168 #define PDC_MAX_GPIO_IRQS 256 #define CLEAR_INTR(reg, intr) (reg & ~(1 << intr)) @@ -42,8 +44,10 @@ struct pdc_pin_region { }; struct spi_cfg_regs { - u64 start; - void __iomem *base; + union { + u64 start; + void __iomem *base; + }; resource_size_t size; bool scm_io; }; @@ -149,7 +153,7 @@ static u32 __spi_pin_read(unsigned int pin) qcom_scm_io_readl(scm_cfg_reg, &val); return val; } else { - return readl_relaxed(cfg_reg); + return readl(cfg_reg); } } @@ -161,7 +165,7 @@ static void __spi_pin_write(unsigned int pin, unsigned int val) if (spi_cfg->scm_io) qcom_scm_io_writel(scm_cfg_reg, val); else - writel_relaxed(val, cfg_reg); + writel(val, cfg_reg); } static int spi_configure_type(irq_hw_number_t hwirq, unsigned int type) @@ -271,6 +275,11 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type) return ret; } + /* Additionally, configure (only) the GPIO in the f/w */ + ret = spi_configure_type(parent_hwirq, type); + if (ret) + return ret; + return irq_chip_set_type_parent(d, type); } diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index c92b405b7646cfbceaed3b6544fb71d145c9bb42..ba8619524231ccde29093076e6196652d17dd69b 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -744,7 +744,7 @@ capi_poll(struct file *file, poll_table *wait) poll_wait(file, &(cdev->recvwait), wait); mask = EPOLLOUT | EPOLLWRNORM; - if (!skb_queue_empty(&cdev->recvqueue)) + if (!skb_queue_empty_lockless(&cdev->recvqueue)) mask |= EPOLLIN | EPOLLRDNORM; return mask; } diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c index 705c6200814b633abf9794b044f3a7b97aa7d269..7b726f00f1834d1cd4aa544090215ad9562e4c08 100644 --- a/drivers/macintosh/windfarm_cpufreq_clamp.c +++ b/drivers/macintosh/windfarm_cpufreq_clamp.c @@ -18,7 +18,7 @@ static int clamped; static struct wf_control *clamp_control; -static struct dev_pm_qos_request qos_req; +static struct freq_qos_request qos_req; static unsigned int min_freq, max_freq; static int clamp_set(struct wf_control *ct, s32 value) @@ -35,7 +35,7 @@ static int clamp_set(struct wf_control *ct, s32 value) } clamped = value; - return dev_pm_qos_update_request(&qos_req, freq); + return freq_qos_update_request(&qos_req, freq); } static int clamp_get(struct wf_control *ct, s32 *value) @@ -77,38 +77,44 @@ static int __init wf_cpufreq_clamp_init(void) min_freq = policy->cpuinfo.min_freq; max_freq = policy->cpuinfo.max_freq; + + ret = freq_qos_add_request(&policy->constraints, &qos_req, FREQ_QOS_MAX, + max_freq); + cpufreq_cpu_put(policy); + if (ret < 0) { + pr_err("%s: Failed to add freq constraint (%d)\n", __func__, + ret); + return ret; + } + dev = get_cpu_device(0); if (unlikely(!dev)) { pr_warn("%s: No cpu device for cpu0\n", __func__); - return -ENODEV; + ret = -ENODEV; + goto fail; } clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); - if (clamp == NULL) - return -ENOMEM; - - ret = dev_pm_qos_add_request(dev, &qos_req, DEV_PM_QOS_MAX_FREQUENCY, - max_freq); - if (ret < 0) { - pr_err("%s: Failed to add freq constraint (%d)\n", __func__, - ret); - goto free; + if (clamp == NULL) { + ret = -ENOMEM; + goto fail; } clamp->ops = &clamp_ops; clamp->name = "cpufreq-clamp"; ret = wf_register_control(clamp); if (ret) - goto fail; + goto free; + clamp_control = clamp; return 0; - fail: - dev_pm_qos_remove_request(&qos_req); free: kfree(clamp); + fail: + freq_qos_remove_request(&qos_req); return ret; } @@ -116,7 +122,7 @@ static void __exit wf_cpufreq_clamp_exit(void) { if (clamp_control) { wf_unregister_control(clamp_control); - dev_pm_qos_remove_request(&qos_req); + freq_qos_remove_request(&qos_req); } } diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index d249cf8ac277e4246d8f398c8aa3b2e46fe90724..8346e6d1816c01bb09cb161ab026f970b520f9e9 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -542,7 +542,7 @@ static void wake_migration_worker(struct cache *cache) static struct dm_bio_prison_cell_v2 *alloc_prison_cell(struct cache *cache) { - return dm_bio_prison_alloc_cell_v2(cache->prison, GFP_NOWAIT); + return dm_bio_prison_alloc_cell_v2(cache->prison, GFP_NOIO); } static void free_prison_cell(struct cache *cache, struct dm_bio_prison_cell_v2 *cell) @@ -554,9 +554,7 @@ static struct dm_cache_migration *alloc_migration(struct cache *cache) { struct dm_cache_migration *mg; - mg = mempool_alloc(&cache->migration_pool, GFP_NOWAIT); - if (!mg) - return NULL; + mg = mempool_alloc(&cache->migration_pool, GFP_NOIO); memset(mg, 0, sizeof(*mg)); @@ -664,10 +662,6 @@ static bool bio_detain_shared(struct cache *cache, dm_oblock_t oblock, struct bi struct dm_bio_prison_cell_v2 *cell_prealloc, *cell; cell_prealloc = alloc_prison_cell(cache); /* FIXME: allow wait if calling from worker */ - if (!cell_prealloc) { - defer_bio(cache, bio); - return false; - } build_key(oblock, end, &key); r = dm_cell_get_v2(cache->prison, &key, lock_level(bio), bio, cell_prealloc, &cell); @@ -1493,11 +1487,6 @@ static int mg_lock_writes(struct dm_cache_migration *mg) struct dm_bio_prison_cell_v2 *prealloc; prealloc = alloc_prison_cell(cache); - if (!prealloc) { - DMERR_LIMIT("%s: alloc_prison_cell failed", cache_device_name(cache)); - mg_complete(mg, false); - return -ENOMEM; - } /* * Prevent writes to the block, but allow reads to continue. @@ -1535,11 +1524,6 @@ static int mg_start(struct cache *cache, struct policy_work *op, struct bio *bio } mg = alloc_migration(cache); - if (!mg) { - policy_complete_background_work(cache->policy, op, false); - background_work_end(cache); - return -ENOMEM; - } mg->op = op; mg->overwrite_bio = bio; @@ -1628,10 +1612,6 @@ static int invalidate_lock(struct dm_cache_migration *mg) struct dm_bio_prison_cell_v2 *prealloc; prealloc = alloc_prison_cell(cache); - if (!prealloc) { - invalidate_complete(mg, false); - return -ENOMEM; - } build_key(mg->invalidate_oblock, oblock_succ(mg->invalidate_oblock), &key); r = dm_cell_lock_v2(cache->prison, &key, @@ -1669,10 +1649,6 @@ static int invalidate_start(struct cache *cache, dm_cblock_t cblock, return -EPERM; mg = alloc_migration(cache); - if (!mg) { - background_work_end(cache); - return -ENOMEM; - } mg->overwrite_bio = bio; mg->invalidate_cblock = cblock; diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c index cd6f9e9fc98e56112c533a45980478bab02d9777..4ca8f19772224a9bc3c3cdc76b1fbe2a7774d20f 100644 --- a/drivers/md/dm-clone-target.c +++ b/drivers/md/dm-clone-target.c @@ -591,8 +591,8 @@ static struct hash_table_bucket *get_hash_table_bucket(struct clone *clone, * * NOTE: Must be called with the bucket lock held */ -struct dm_clone_region_hydration *__hash_find(struct hash_table_bucket *bucket, - unsigned long region_nr) +static struct dm_clone_region_hydration *__hash_find(struct hash_table_bucket *bucket, + unsigned long region_nr) { struct dm_clone_region_hydration *hd; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index f150f5c5492b9fe3fdf02e3e5f24dd120fd609fc..4fb1a40e68a08748b94069802c1d8f666bcb7566 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "dm.h" @@ -107,8 +106,8 @@ struct dm_snapshot { /* The on disk metadata handler */ struct dm_exception_store *store; - /* Maximum number of in-flight COW jobs. */ - struct semaphore cow_count; + unsigned in_progress; + struct wait_queue_head in_progress_wait; struct dm_kcopyd_client *kcopyd_client; @@ -162,8 +161,8 @@ struct dm_snapshot { */ #define DEFAULT_COW_THRESHOLD 2048 -static int cow_threshold = DEFAULT_COW_THRESHOLD; -module_param_named(snapshot_cow_threshold, cow_threshold, int, 0644); +static unsigned cow_threshold = DEFAULT_COW_THRESHOLD; +module_param_named(snapshot_cow_threshold, cow_threshold, uint, 0644); MODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write"); DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle, @@ -1327,7 +1326,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad_hash_tables; } - sema_init(&s->cow_count, (cow_threshold > 0) ? cow_threshold : INT_MAX); + init_waitqueue_head(&s->in_progress_wait); s->kcopyd_client = dm_kcopyd_client_create(&dm_kcopyd_throttle); if (IS_ERR(s->kcopyd_client)) { @@ -1509,9 +1508,56 @@ static void snapshot_dtr(struct dm_target *ti) dm_put_device(ti, s->origin); + WARN_ON(s->in_progress); + kfree(s); } +static void account_start_copy(struct dm_snapshot *s) +{ + spin_lock(&s->in_progress_wait.lock); + s->in_progress++; + spin_unlock(&s->in_progress_wait.lock); +} + +static void account_end_copy(struct dm_snapshot *s) +{ + spin_lock(&s->in_progress_wait.lock); + BUG_ON(!s->in_progress); + s->in_progress--; + if (likely(s->in_progress <= cow_threshold) && + unlikely(waitqueue_active(&s->in_progress_wait))) + wake_up_locked(&s->in_progress_wait); + spin_unlock(&s->in_progress_wait.lock); +} + +static bool wait_for_in_progress(struct dm_snapshot *s, bool unlock_origins) +{ + if (unlikely(s->in_progress > cow_threshold)) { + spin_lock(&s->in_progress_wait.lock); + if (likely(s->in_progress > cow_threshold)) { + /* + * NOTE: this throttle doesn't account for whether + * the caller is servicing an IO that will trigger a COW + * so excess throttling may result for chunks not required + * to be COW'd. But if cow_threshold was reached, extra + * throttling is unlikely to negatively impact performance. + */ + DECLARE_WAITQUEUE(wait, current); + __add_wait_queue(&s->in_progress_wait, &wait); + __set_current_state(TASK_UNINTERRUPTIBLE); + spin_unlock(&s->in_progress_wait.lock); + if (unlock_origins) + up_read(&_origins_lock); + io_schedule(); + remove_wait_queue(&s->in_progress_wait, &wait); + return false; + } + spin_unlock(&s->in_progress_wait.lock); + } + return true; +} + /* * Flush a list of buffers. */ @@ -1527,7 +1573,7 @@ static void flush_bios(struct bio *bio) } } -static int do_origin(struct dm_dev *origin, struct bio *bio); +static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit); /* * Flush a list of buffers. @@ -1540,7 +1586,7 @@ static void retry_origin_bios(struct dm_snapshot *s, struct bio *bio) while (bio) { n = bio->bi_next; bio->bi_next = NULL; - r = do_origin(s->origin, bio); + r = do_origin(s->origin, bio, false); if (r == DM_MAPIO_REMAPPED) generic_make_request(bio); bio = n; @@ -1732,7 +1778,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context) rb_link_node(&pe->out_of_order_node, parent, p); rb_insert_color(&pe->out_of_order_node, &s->out_of_order_tree); } - up(&s->cow_count); + account_end_copy(s); } /* @@ -1756,7 +1802,7 @@ static void start_copy(struct dm_snap_pending_exception *pe) dest.count = src.count; /* Hand over to kcopyd */ - down(&s->cow_count); + account_start_copy(s); dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe); } @@ -1776,7 +1822,7 @@ static void start_full_bio(struct dm_snap_pending_exception *pe, pe->full_bio = bio; pe->full_bio_end_io = bio->bi_end_io; - down(&s->cow_count); + account_start_copy(s); callback_data = dm_kcopyd_prepare_callback(s->kcopyd_client, copy_callback, pe); @@ -1866,7 +1912,7 @@ static void zero_callback(int read_err, unsigned long write_err, void *context) struct bio *bio = context; struct dm_snapshot *s = bio->bi_private; - up(&s->cow_count); + account_end_copy(s); bio->bi_status = write_err ? BLK_STS_IOERR : 0; bio_endio(bio); } @@ -1880,7 +1926,7 @@ static void zero_exception(struct dm_snapshot *s, struct dm_exception *e, dest.sector = bio->bi_iter.bi_sector; dest.count = s->store->chunk_size; - down(&s->cow_count); + account_start_copy(s); WARN_ON_ONCE(bio->bi_private); bio->bi_private = s; dm_kcopyd_zero(s->kcopyd_client, 1, &dest, 0, zero_callback, bio); @@ -1916,6 +1962,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio) if (!s->valid) return DM_MAPIO_KILL; + if (bio_data_dir(bio) == WRITE) { + while (unlikely(!wait_for_in_progress(s, false))) + ; /* wait_for_in_progress() has slept */ + } + down_read(&s->lock); dm_exception_table_lock(&lock); @@ -2112,7 +2163,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio) if (bio_data_dir(bio) == WRITE) { up_write(&s->lock); - return do_origin(s->origin, bio); + return do_origin(s->origin, bio, false); } out_unlock: @@ -2487,15 +2538,24 @@ static int __origin_write(struct list_head *snapshots, sector_t sector, /* * Called on a write from the origin driver. */ -static int do_origin(struct dm_dev *origin, struct bio *bio) +static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit) { struct origin *o; int r = DM_MAPIO_REMAPPED; +again: down_read(&_origins_lock); o = __lookup_origin(origin->bdev); - if (o) + if (o) { + if (limit) { + struct dm_snapshot *s; + list_for_each_entry(s, &o->snapshots, list) + if (unlikely(!wait_for_in_progress(s, true))) + goto again; + } + r = __origin_write(&o->snapshots, bio->bi_iter.bi_sector, bio); + } up_read(&_origins_lock); return r; @@ -2608,7 +2668,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio) dm_accept_partial_bio(bio, available_sectors); /* Only tell snapshots if this is a write */ - return do_origin(o->dev, bio); + return do_origin(o->dev, bio, true); } /* diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 1a5e328c443a997a48e36a0397afbe27ee8c8e4b..67c24294d7c87a97d1219e5ec1d5ec04fcf430dd 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1322,12 +1322,15 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio, sector_t sector, unsigned len) { struct bio *clone = &tio->clone; + int ret; __bio_clone_fast(clone, bio); - if (bio_integrity(bio)) { - int r; + ret = bio_crypt_clone(clone, bio, GFP_NOIO); + if (ret < 0) + return ret; + if (bio_integrity(bio)) { if (unlikely(!dm_target_has_integrity(tio->ti->type) && !dm_target_passes_integrity(tio->ti->type))) { DMWARN("%s: the target %s doesn't support integrity data.", @@ -1336,9 +1339,11 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio, return -EIO; } - r = bio_integrity_clone(clone, bio, GFP_NOIO); - if (r < 0) - return r; + ret = bio_integrity_clone(clone, bio, GFP_NOIO); + if (ret < 0) { + bio_crypt_free_ctx(clone); + return ret; + } } bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector)); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index f61693e596845aebafbbedb8f940e0eaec9b0bee..1e772287b1c8e7fa2ec54724c12d69526fbc57fa 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -154,7 +154,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) } else { pr_err("md/raid0:%s: cannot assemble multi-zone RAID0 with default_layout setting\n", mdname(mddev)); - pr_err("md/raid0: please set raid.default_layout to 1 or 2\n"); + pr_err("md/raid0: please set raid0.default_layout to 1 or 2\n"); err = -ENOTSUPP; goto abort; } diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index e1eaf1135c7f88d3a09a7b7d26dd027b50e4cbc5..e4e454db256066479f1f1d42e3f9c6b0566bb0fb 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -465,6 +465,11 @@ struct v4l2_plane32 { __s32 fd; } m; __u32 data_offset; + /* + * few userspace clients and drivers use reserved fields + * and it is up to them how these fields are used. v4l2 + * simply copy reserved fields between them. + */ __u32 reserved[11]; }; @@ -499,7 +504,9 @@ static int get_v4l2_plane32(struct v4l2_plane __user *p64, if (copy_in_user(p64, p32, 2 * sizeof(__u32)) || copy_in_user(&p64->data_offset, &p32->data_offset, - sizeof(p64->data_offset))) + sizeof(p64->data_offset)) || + copy_in_user(p64->reserved, p32->reserved, + sizeof(p64->reserved))) return -EFAULT; switch (memory) { @@ -531,7 +538,9 @@ static int put_v4l2_plane32(struct v4l2_plane __user *p64, if (copy_in_user(p32, p64, 2 * sizeof(__u32)) || copy_in_user(&p32->data_offset, &p64->data_offset, - sizeof(p64->data_offset))) + sizeof(p64->data_offset)) || + copy_in_user(p32->reserved, p64->reserved, + sizeof(p32->reserved))) return -EFAULT; switch (memory) { diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 32747425297d840ba4458c6345946b07fec8ba85..64fff6abe60e8394782089931e59e374b68ee5bf 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -941,7 +941,7 @@ static int jmb38x_ms_probe(struct pci_dev *pdev, if (!cnt) { rc = -ENODEV; pci_dev_busy = 1; - goto err_out; + goto err_out_int; } jm = kzalloc(sizeof(struct jmb38x_ms) diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 310dae26ddff6283a0b83c05cd5c31b73834cf97..b2c325ead1c8f08b594a9da913ec5013e3068abc 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -129,11 +129,27 @@ static int mt6397_irq_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend, mt6397_irq_resume); +struct chip_data { + u32 cid_addr; + u32 cid_shift; +}; + +static const struct chip_data mt6323_core = { + .cid_addr = MT6323_CID, + .cid_shift = 0, +}; + +static const struct chip_data mt6397_core = { + .cid_addr = MT6397_CID, + .cid_shift = 0, +}; + static int mt6397_probe(struct platform_device *pdev) { int ret; unsigned int id; struct mt6397_chip *pmic; + const struct chip_data *pmic_core; pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) @@ -149,28 +165,30 @@ static int mt6397_probe(struct platform_device *pdev) if (!pmic->regmap) return -ENODEV; - platform_set_drvdata(pdev, pmic); + pmic_core = of_device_get_match_data(&pdev->dev); + if (!pmic_core) + return -ENODEV; - ret = regmap_read(pmic->regmap, MT6397_CID, &id); + ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id); if (ret) { - dev_err(pmic->dev, "Failed to read chip id: %d\n", ret); + dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret); return ret; } + pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff; + + platform_set_drvdata(pdev, pmic); + pmic->irq = platform_get_irq(pdev, 0); if (pmic->irq <= 0) return pmic->irq; - switch (id & 0xff) { - case MT6323_CHIP_ID: - pmic->int_con[0] = MT6323_INT_CON0; - pmic->int_con[1] = MT6323_INT_CON1; - pmic->int_status[0] = MT6323_INT_STATUS0; - pmic->int_status[1] = MT6323_INT_STATUS1; - ret = mt6397_irq_init(pmic); - if (ret) - return ret; + ret = mt6397_irq_init(pmic); + if (ret) + return ret; + switch (pmic->chip_id) { + case MT6323_CHIP_ID: ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, ARRAY_SIZE(mt6323_devs), NULL, 0, pmic->irq_domain); @@ -178,21 +196,13 @@ static int mt6397_probe(struct platform_device *pdev) case MT6391_CHIP_ID: case MT6397_CHIP_ID: - pmic->int_con[0] = MT6397_INT_CON0; - pmic->int_con[1] = MT6397_INT_CON1; - pmic->int_status[0] = MT6397_INT_STATUS0; - pmic->int_status[1] = MT6397_INT_STATUS1; - ret = mt6397_irq_init(pmic); - if (ret) - return ret; - ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, ARRAY_SIZE(mt6397_devs), NULL, 0, pmic->irq_domain); break; default: - dev_err(&pdev->dev, "unsupported chip: %d\n", id); + dev_err(&pdev->dev, "unsupported chip: %d\n", pmic->chip_id); return -ENODEV; } @@ -205,9 +215,15 @@ static int mt6397_probe(struct platform_device *pdev) } static const struct of_device_id mt6397_of_match[] = { - { .compatible = "mediatek,mt6397" }, - { .compatible = "mediatek,mt6323" }, - { } + { + .compatible = "mediatek,mt6323", + .data = &mt6323_core, + }, { + .compatible = "mediatek,mt6397", + .data = &mt6397_core, + }, { + /* sentinel */ + } }; MODULE_DEVICE_TABLE(of, mt6397_of_match); diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index f7bdae5354c3c48af7bb26d828b83227b057d8bf..5047f7343ffcf41ce3a861ffbb104ac2f6586806 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -611,7 +611,8 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) cq_host->slot[tag].flags = 0; cq_host->qcnt += 1; - + /* Make sure descriptors are ready before ringing the doorbell */ + wmb(); cqhci_writel(cq_host, 1 << tag, CQHCI_TDBR); if (!(cqhci_readl(cq_host, CQHCI_TDBR) & (1 << tag))) pr_debug("%s: cqhci: doorbell not set for tag %d\n", diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 78e7e350655c7f742970757a4117a8bc00ca8fc5..4031217d21c37be1a847ace9d8369c041ab95561 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -266,7 +267,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host) ssp->ssp_pio_words[2] = cmd1; ssp->dma_dir = DMA_NONE; ssp->slave_dirn = DMA_TRANS_NONE; - desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK); + desc = mxs_mmc_prep_dma(host, MXS_DMA_CTRL_WAIT4END); if (!desc) goto out; @@ -311,7 +312,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host) ssp->ssp_pio_words[2] = cmd1; ssp->dma_dir = DMA_NONE; ssp->slave_dirn = DMA_TRANS_NONE; - desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK); + desc = mxs_mmc_prep_dma(host, MXS_DMA_CTRL_WAIT4END); if (!desc) goto out; @@ -441,7 +442,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) host->data = data; ssp->dma_dir = dma_data_dir; ssp->slave_dirn = slave_dirn; - desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | MXS_DMA_CTRL_WAIT4END); if (!desc) goto out; diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index d4ada5cca2d14f6a041e9723b41d5ae8618c718f..234551a68739b65b0ccc3de9b0967ccaff12a3b9 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -646,8 +646,8 @@ int renesas_sdhi_probe(struct platform_device *pdev, struct tmio_mmc_dma *dma_priv; struct tmio_mmc_host *host; struct renesas_sdhi *priv; + int num_irqs, irq, ret, i; struct resource *res; - int irq, ret, i; u16 ver; of_data = of_device_get_match_data(&pdev->dev); @@ -825,24 +825,31 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->hs400_complete = renesas_sdhi_hs400_complete; } - i = 0; - while (1) { + num_irqs = platform_irq_count(pdev); + if (num_irqs < 0) { + ret = num_irqs; + goto eirq; + } + + /* There must be at least one IRQ source */ + if (!num_irqs) { + ret = -ENXIO; + goto eirq; + } + + for (i = 0; i < num_irqs; i++) { irq = platform_get_irq(pdev, i); - if (irq < 0) - break; - i++; + if (irq < 0) { + ret = irq; + goto eirq; + } + ret = devm_request_irq(&pdev->dev, irq, tmio_mmc_irq, 0, dev_name(&pdev->dev), host); if (ret) goto eirq; } - /* There must be at least one IRQ source */ - if (!i) { - ret = irq; - goto eirq; - } - dev_info(&pdev->dev, "%s base at 0x%08lx max clock rate %u MHz\n", mmc_hostname(host->mmc), (unsigned long) (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start), diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index 2b9cdcd1dd9dd6ffaa458ebd6f7fdc908a6954cf..f4f5f0a70cda8a1d90b3e3a77ca21f318f34b4d7 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -262,6 +262,7 @@ static const struct sdhci_iproc_data bcm2835_data = { }; static const struct sdhci_pltfm_data sdhci_bcm2711_pltfm_data = { + .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, .ops = &sdhci_iproc_32only_ops, }; diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 41c2677c587f1677366ed14f65cc50cc3da7da96..083e7e053c95401bcc6e87c6e8d5e3a52605e474 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -372,7 +372,7 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) * on temperature */ if (temperature < -20000) - phase_delay = min(max_window + 4 * max_len - 24, + phase_delay = min(max_window + 4 * (max_len - 1) - 24, max_window + DIV_ROUND_UP(13 * max_len, 16) * 4); else if (temperature < 20000) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 81bd9afb0980525e23658953e03b6e9dcb1e2c33..98c575de43c755ed5772150d1bdbb6538a143332 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1393,11 +1393,9 @@ static int sh_mmcif_probe(struct platform_device *pdev) const char *name; irq[0] = platform_get_irq(pdev, 0); - irq[1] = platform_get_irq(pdev, 1); - if (irq[0] < 0) { - dev_err(dev, "Get irq error\n"); + irq[1] = platform_get_irq_optional(pdev, 1); + if (irq[0] < 0) return -ENXIO; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg = devm_ioremap_resource(dev, res); diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 8c79bad2a9a57dfd9f1841add3597590ab02e3db..4f2e6910c6232618ab536c83cdc83ba1a398b041 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -952,7 +952,7 @@ static int alb_upper_dev_walk(struct net_device *upper, void *_data) struct bond_vlan_tag *tags; if (is_vlan_dev(upper) && - bond->nest_level == vlan_get_encap_level(upper) - 1) { + bond->dev->lower_level == upper->lower_level - 1) { if (upper->addr_assign_type == NET_ADDR_STOLEN) { alb_send_lp_vid(slave, mac_addr, vlan_dev_vlan_proto(upper), diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 931d9d9356869b400c1b653414164a3e5ecb0b51..480f9459b402c578ac1b09f8c48ae2a730852c3c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1733,8 +1733,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, goto err_upper_unlink; } - bond->nest_level = dev_get_nest_level(bond_dev) + 1; - /* If the mode uses primary, then the following is handled by * bond_change_active_slave(). */ @@ -1816,7 +1814,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, slave_disable_netpoll(new_slave); err_close: - slave_dev->priv_flags &= ~IFF_BONDING; + if (!netif_is_bond_master(slave_dev)) + slave_dev->priv_flags &= ~IFF_BONDING; dev_close(slave_dev); err_restore_mac: @@ -1956,9 +1955,6 @@ static int __bond_release_one(struct net_device *bond_dev, if (!bond_has_slaves(bond)) { bond_set_carrier(bond); eth_hw_addr_random(bond_dev); - bond->nest_level = SINGLE_DEPTH_NESTING; - } else { - bond->nest_level = dev_get_nest_level(bond_dev) + 1; } unblock_netpoll_tx(); @@ -2017,7 +2013,8 @@ static int __bond_release_one(struct net_device *bond_dev, else dev_set_mtu(slave_dev, slave->original_mtu); - slave_dev->priv_flags &= ~IFF_BONDING; + if (!netif_is_bond_master(slave_dev)) + slave_dev->priv_flags &= ~IFF_BONDING; bond_free_slave(slave); @@ -3442,13 +3439,6 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res, } } -static int bond_get_nest_level(struct net_device *bond_dev) -{ - struct bonding *bond = netdev_priv(bond_dev); - - return bond->nest_level; -} - static void bond_get_stats(struct net_device *bond_dev, struct rtnl_link_stats64 *stats) { @@ -3457,7 +3447,7 @@ static void bond_get_stats(struct net_device *bond_dev, struct list_head *iter; struct slave *slave; - spin_lock_nested(&bond->stats_lock, bond_get_nest_level(bond_dev)); + spin_lock(&bond->stats_lock); memcpy(stats, &bond->bond_stats, sizeof(*stats)); rcu_read_lock(); @@ -4039,7 +4029,7 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave) * this to-be-skipped slave to send a packet out. */ old_arr = rtnl_dereference(bond->slave_arr); - for (idx = 0; idx < old_arr->count; idx++) { + for (idx = 0; old_arr != NULL && idx < old_arr->count; idx++) { if (skipslave == old_arr->arr[idx]) { old_arr->arr[idx] = old_arr->arr[old_arr->count-1]; @@ -4268,7 +4258,6 @@ static const struct net_device_ops bond_netdev_ops = { .ndo_neigh_setup = bond_neigh_setup, .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, - .ndo_get_lock_subclass = bond_get_nest_level, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_netpoll_setup = bond_netpoll_setup, .ndo_netpoll_cleanup = bond_netpoll_cleanup, @@ -4296,7 +4285,6 @@ void bond_setup(struct net_device *bond_dev) struct bonding *bond = netdev_priv(bond_dev); spin_lock_init(&bond->mode_lock); - spin_lock_init(&bond->stats_lock); bond->params = bonding_defaults; /* Initialize pointers */ @@ -4365,6 +4353,7 @@ static void bond_uninit(struct net_device *bond_dev) list_del(&bond->bond_list); + lockdep_unregister_key(&bond->stats_lock_key); bond_debug_unregister(bond); } @@ -4768,8 +4757,9 @@ static int bond_init(struct net_device *bond_dev) if (!bond->wq) return -ENOMEM; - bond->nest_level = SINGLE_DEPTH_NESTING; - netdev_lockdep_set_classes(bond_dev); + spin_lock_init(&bond->stats_lock); + lockdep_register_key(&bond->stats_lock_key); + lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key); list_add_tail(&bond->bond_list, &bn->dev_list); diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 526ba2ab66f10b027ec5861d481be26a26e890af..cc3536315eff55c5bbc1942f09490fa44ca900e7 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1845,7 +1845,6 @@ int b53_mirror_add(struct dsa_switch *ds, int port, loc = B53_EG_MIR_CTL; b53_read16(dev, B53_MGMT_PAGE, loc, ®); - reg &= ~MIRROR_MASK; reg |= BIT(port); b53_write16(dev, B53_MGMT_PAGE, loc, reg); diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 26509fa37a50b4d4137adfef9878ac969464da18..d44651ad520c10d7e21d5f7793baab248e389b7c 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -37,22 +37,11 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) unsigned int i; u32 reg, offset; - if (priv->type == BCM7445_DEVICE_ID) - offset = CORE_STS_OVERRIDE_IMP; - else - offset = CORE_STS_OVERRIDE_IMP2; - /* Enable the port memories */ reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL); reg &= ~P_TXQ_PSM_VDD(port); core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL); - /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */ - reg = core_readl(priv, CORE_IMP_CTL); - reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN); - reg &= ~(RX_DIS | TX_DIS); - core_writel(priv, reg, CORE_IMP_CTL); - /* Enable forwarding */ core_writel(priv, SW_FWDG_EN, CORE_SWMODE); @@ -71,10 +60,27 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) b53_brcm_hdr_setup(ds, port); - /* Force link status for IMP port */ - reg = core_readl(priv, offset); - reg |= (MII_SW_OR | LINK_STS); - core_writel(priv, reg, offset); + if (port == 8) { + if (priv->type == BCM7445_DEVICE_ID) + offset = CORE_STS_OVERRIDE_IMP; + else + offset = CORE_STS_OVERRIDE_IMP2; + + /* Force link status for IMP port */ + reg = core_readl(priv, offset); + reg |= (MII_SW_OR | LINK_STS); + core_writel(priv, reg, offset); + + /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */ + reg = core_readl(priv, CORE_IMP_CTL); + reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN); + reg &= ~(RX_DIS | TX_DIS); + core_writel(priv, reg, CORE_IMP_CTL); + } else { + reg = core_readl(priv, CORE_G_PCTL_PORT(port)); + reg &= ~(RX_DIS | TX_DIS); + core_writel(priv, reg, CORE_G_PCTL_PORT(port)); + } } static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable) diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index a23d3ffdf0c4d5c95d555229b8740e2f69500e4e..24a5e99f7fd5b5ee66252ca7b41963f24d090d81 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -1224,10 +1224,6 @@ static int ksz8795_switch_init(struct ksz_device *dev) { int i; - mutex_init(&dev->stats_mutex); - mutex_init(&dev->alu_mutex); - mutex_init(&dev->vlan_mutex); - dev->ds->ops = &ksz8795_switch_ops; for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) { diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c index d0f8153e86b7d7bddcde1cd30b305c4e6a69b5f5..8b00f8e6c02f4f2a2fbc545c026cb2daaa48528c 100644 --- a/drivers/net/dsa/microchip/ksz8795_spi.c +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -25,6 +25,7 @@ KSZ_REGMAP_TABLE(ksz8795, 16, SPI_ADDR_SHIFT, static int ksz8795_spi_probe(struct spi_device *spi) { + struct regmap_config rc; struct ksz_device *dev; int i, ret; @@ -33,9 +34,9 @@ static int ksz8795_spi_probe(struct spi_device *spi) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { - dev->regmap[i] = devm_regmap_init_spi(spi, - &ksz8795_regmap_config - [i]); + rc = ksz8795_regmap_config[i]; + rc.lock_arg = &dev->regmap_mutex; + dev->regmap[i] = devm_regmap_init_spi(spi, &rc); if (IS_ERR(dev->regmap[i])) { ret = PTR_ERR(dev->regmap[i]); dev_err(&spi->dev, diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index 0b1e01f0873d5733336e3c291148f5993494f3c1..fdffd9e0c518b53d0f55e4bb1fe5975ddcebed58 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -17,6 +17,7 @@ KSZ_REGMAP_TABLE(ksz9477, not_used, 16, 0, 0); static int ksz9477_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) { + struct regmap_config rc; struct ksz_device *dev; int i, ret; @@ -25,8 +26,9 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c, return -ENOMEM; for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_config); i++) { - dev->regmap[i] = devm_regmap_init_i2c(i2c, - &ksz9477_regmap_config[i]); + rc = ksz9477_regmap_config[i]; + rc.lock_arg = &dev->regmap_mutex; + dev->regmap[i] = devm_regmap_init_i2c(i2c, &rc); if (IS_ERR(dev->regmap[i])) { ret = PTR_ERR(dev->regmap[i]); dev_err(&i2c->dev, diff --git a/drivers/net/dsa/microchip/ksz9477_reg.h b/drivers/net/dsa/microchip/ksz9477_reg.h index 2938e892b6316b5f5d65ff6d0588e611b0cabf40..16939f29faa5ec7f13de863bae18d973012209f4 100644 --- a/drivers/net/dsa/microchip/ksz9477_reg.h +++ b/drivers/net/dsa/microchip/ksz9477_reg.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0 */ +/* * Microchip KSZ9477 register definitions * * Copyright (C) 2017-2018 Microchip Technology Inc. diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c index f4198d6f72bee55a6ba4f0dca945f0d701870d82..c5f64959a184e25b25adc68f33543a6236b2f874 100644 --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@ -24,6 +24,7 @@ KSZ_REGMAP_TABLE(ksz9477, 32, SPI_ADDR_SHIFT, static int ksz9477_spi_probe(struct spi_device *spi) { + struct regmap_config rc; struct ksz_device *dev; int i, ret; @@ -32,8 +33,9 @@ static int ksz9477_spi_probe(struct spi_device *spi) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_config); i++) { - dev->regmap[i] = devm_regmap_init_spi(spi, - &ksz9477_regmap_config[i]); + rc = ksz9477_regmap_config[i]; + rc.lock_arg = &dev->regmap_mutex; + dev->regmap[i] = devm_regmap_init_spi(spi, &rc); if (IS_ERR(dev->regmap[i])) { ret = PTR_ERR(dev->regmap[i]); dev_err(&spi->dev, diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index b0b870f0c252095f7844230b3e3fe700e14d75fe..fe47180c908b979fe9df3d40ee6729ca9d78828f 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -436,7 +436,7 @@ int ksz_switch_register(struct ksz_device *dev, } mutex_init(&dev->dev_mutex); - mutex_init(&dev->stats_mutex); + mutex_init(&dev->regmap_mutex); mutex_init(&dev->alu_mutex); mutex_init(&dev->vlan_mutex); diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index dd60d0837fc6db51f744db06fb26f1eeefb83673..a20ebb749377c1356506aabb1ded804d916d4a0e 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 - * Microchip switch driver common header +/* SPDX-License-Identifier: GPL-2.0 */ +/* Microchip switch driver common header * * Copyright (C) 2017-2019 Microchip Technology Inc. */ @@ -47,7 +47,7 @@ struct ksz_device { const char *name; struct mutex dev_mutex; /* device access */ - struct mutex stats_mutex; /* status access */ + struct mutex regmap_mutex; /* regmap access */ struct mutex alu_mutex; /* ALU access */ struct mutex vlan_mutex; /* vlan access */ const struct ksz_dev_ops *dev_ops; @@ -290,6 +290,18 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset, ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data); } +static inline void ksz_regmap_lock(void *__mtx) +{ + struct mutex *mtx = __mtx; + mutex_lock(mtx); +} + +static inline void ksz_regmap_unlock(void *__mtx) +{ + struct mutex *mtx = __mtx; + mutex_unlock(mtx); +} + /* Regmap tables generation */ #define KSZ_SPI_OP_RD 3 #define KSZ_SPI_OP_WR 2 @@ -314,6 +326,8 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset, .write_flag_mask = \ KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_WR, swp, \ regbits, regpad), \ + .lock = ksz_regmap_lock, \ + .unlock = ksz_regmap_unlock, \ .reg_format_endian = REGMAP_ENDIAN_BIG, \ .val_format_endian = REGMAP_ENDIAN_BIG \ } diff --git a/drivers/net/dsa/sja1105/Kconfig b/drivers/net/dsa/sja1105/Kconfig index f40b248f0b23a5581ffa3b3eefd69e4369f3c79b..ffac0ea4e8d56e61cb17858c3f9e1aac96b08885 100644 --- a/drivers/net/dsa/sja1105/Kconfig +++ b/drivers/net/dsa/sja1105/Kconfig @@ -26,8 +26,8 @@ config NET_DSA_SJA1105_PTP config NET_DSA_SJA1105_TAS bool "Support for the Time-Aware Scheduler on NXP SJA1105" - depends on NET_DSA_SJA1105 - depends on NET_SCH_TAPRIO + depends on NET_DSA_SJA1105 && NET_SCH_TAPRIO + depends on NET_SCH_TAPRIO=y || NET_DSA_SJA1105=m help This enables support for the TTEthernet-based egress scheduling engine in the SJA1105 DSA driver, which is controlled using a diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index e53e494c22e09825c3a8bfcedb24d936de8474e9..fbb564c3beb8db1d6c6aff983cfa6363114bf42a 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 - * Copyright (c) 2018, Sensor-Technik Wiedemann GmbH +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2018, Sensor-Technik Wiedemann GmbH * Copyright (c) 2018-2019, Vladimir Oltean */ #ifndef _SJA1105_H diff --git a/drivers/net/dsa/sja1105/sja1105_dynamic_config.h b/drivers/net/dsa/sja1105/sja1105_dynamic_config.h index 740dadf43f0197338e7e5f8387e558357cc6509e..1fc0d13dc623faca9a9213114387e4b9d6f98725 100644 --- a/drivers/net/dsa/sja1105/sja1105_dynamic_config.h +++ b/drivers/net/dsa/sja1105/sja1105_dynamic_config.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 - * Copyright (c) 2019, Vladimir Oltean +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019, Vladimir Oltean */ #ifndef _SJA1105_DYNAMIC_CONFIG_H #define _SJA1105_DYNAMIC_CONFIG_H diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.h b/drivers/net/dsa/sja1105/sja1105_ptp.h index af456b0a4d27696746586b5fdd16654d17c2323e..394e12a6ad59ba22ae556561e75b03c014b95117 100644 --- a/drivers/net/dsa/sja1105/sja1105_ptp.h +++ b/drivers/net/dsa/sja1105/sja1105_ptp.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 - * Copyright (c) 2019, Vladimir Oltean +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019, Vladimir Oltean */ #ifndef _SJA1105_PTP_H #define _SJA1105_PTP_H diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index 7f87022a2d61a82a77721b74613a931aa7f972f1..f4a5c5c043116748a07deeb1fbd93b5c8f7c3f77 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright (c) 2016-2018, NXP Semiconductors +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2016-2018, NXP Semiconductors * Copyright (c) 2018-2019, Vladimir Oltean */ #ifndef _SJA1105_STATIC_CONFIG_H diff --git a/drivers/net/dsa/sja1105/sja1105_tas.h b/drivers/net/dsa/sja1105/sja1105_tas.h index 0b803c30e64073f716abb0ca07ece61cb2fe1a45..0aad212d88b2e07912da1ef048146ff2f19e747e 100644 --- a/drivers/net/dsa/sja1105/sja1105_tas.h +++ b/drivers/net/dsa/sja1105/sja1105_tas.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 - * Copyright (c) 2019, Vladimir Oltean +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019, Vladimir Oltean */ #ifndef _SJA1105_TAS_H #define _SJA1105_TAS_H diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c index b4a0fb281e69ea2631db1e6e45373e0d5a556a27..bb65dd39f847404d64497835a9b03e20d6e2bbde 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c @@ -194,9 +194,7 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev) { struct aq_nic_s *aq_nic = netdev_priv(ndev); - aq_nic_set_packet_filter(aq_nic, ndev->flags); - - aq_nic_set_multicast_list(aq_nic, ndev); + (void)aq_nic_set_multicast_list(aq_nic, ndev); } static int aq_ndo_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 8f66e781781182e553c53ba73fde92581de21ee7..137c1de4c6ec04b3b416ad07013b9e0cf2bc4da3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -631,9 +631,12 @@ int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags) int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) { - unsigned int packet_filter = self->packet_filter; + const struct aq_hw_ops *hw_ops = self->aq_hw_ops; + struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; + unsigned int packet_filter = ndev->flags; struct netdev_hw_addr *ha = NULL; unsigned int i = 0U; + int err = 0; self->mc_list.count = 0; if (netdev_uc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) { @@ -641,29 +644,28 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) } else { netdev_for_each_uc_addr(ha, ndev) { ether_addr_copy(self->mc_list.ar[i++], ha->addr); - - if (i >= AQ_HW_MULTICAST_ADDRESS_MAX) - break; } } - if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) { - packet_filter |= IFF_ALLMULTI; - } else { - netdev_for_each_mc_addr(ha, ndev) { - ether_addr_copy(self->mc_list.ar[i++], ha->addr); - - if (i >= AQ_HW_MULTICAST_ADDRESS_MAX) - break; + cfg->is_mc_list_enabled = !!(packet_filter & IFF_MULTICAST); + if (cfg->is_mc_list_enabled) { + if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) { + packet_filter |= IFF_ALLMULTI; + } else { + netdev_for_each_mc_addr(ha, ndev) { + ether_addr_copy(self->mc_list.ar[i++], + ha->addr); + } } } if (i > 0 && i <= AQ_HW_MULTICAST_ADDRESS_MAX) { - packet_filter |= IFF_MULTICAST; self->mc_list.count = i; - self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, - self->mc_list.ar, - self->mc_list.count); + err = hw_ops->hw_multicast_list_set(self->aq_hw, + self->mc_list.ar, + self->mc_list.count); + if (err < 0) + return err; } return aq_nic_set_packet_filter(self, packet_filter); } diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 3901d7994ca1571500253855c8d613706eacfa80..76bdbe1596d62f10ce3e60ed0de1f1e2175dc435 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -313,6 +313,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, break; buff->is_error |= buff_->is_error; + buff->is_cso_err |= buff_->is_cso_err; } while (!buff_->is_eop); @@ -320,7 +321,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, err = 0; goto err_exit; } - if (buff->is_error) { + if (buff->is_error || buff->is_cso_err) { buff_ = buff; do { next_ = buff_->next, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 30f7fc4c97ff45c979c80155237da8b365628251..2ad3fa6316ce3271ecb7be8081fdcf3e505e98d0 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -818,14 +818,15 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self, cfg->is_vlan_force_promisc); hw_atl_rpfl2multicast_flr_en_set(self, - IS_FILTER_ENABLED(IFF_ALLMULTI), 0); + IS_FILTER_ENABLED(IFF_ALLMULTI) && + IS_FILTER_ENABLED(IFF_MULTICAST), 0); hw_atl_rpfl2_accept_all_mc_packets_set(self, - IS_FILTER_ENABLED(IFF_ALLMULTI)); + IS_FILTER_ENABLED(IFF_ALLMULTI) && + IS_FILTER_ENABLED(IFF_MULTICAST)); hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST)); - cfg->is_mc_list_enabled = IS_FILTER_ENABLED(IFF_MULTICAST); for (i = HW_ATL_B0_MAC_MIN; i < HW_ATL_B0_MAC_MAX; ++i) hw_atl_rpfl2_uc_flr_en_set(self, @@ -968,14 +969,26 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) static int hw_atl_b0_hw_stop(struct aq_hw_s *self) { + int err; + u32 val; + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); /* Invalidate Descriptor Cache to prevent writing to the cached * descriptors and to the data pointer of those descriptors */ - hw_atl_rdm_rx_dma_desc_cache_init_set(self, 1); + hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); - return aq_hw_err_from_flags(self); + err = aq_hw_err_from_flags(self); + + if (err) + goto err_exit; + + readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, + self, val, val == 1, 1000U, 10000U); + +err_exit: + return err; } static int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c index 1149812ae463415298c959b0b1458b636e1d13ab..6f340695e6bd2383b316a440e3e9f1e8e20ca1a2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c @@ -606,12 +606,25 @@ void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode HW_ATL_RPB_RX_FC_MODE_SHIFT, rx_flow_ctl_mode); } -void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init) +void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw) { + u32 val; + + val = aq_hw_read_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR, + HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK, + HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT); + aq_hw_write_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT, - init); + val ^ 1); +} + +u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw) +{ + return aq_hw_read_reg_bit(aq_hw, RDM_RX_DMA_DESC_CACHE_INIT_DONE_ADR, + RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSK, + RDM_RX_DMA_DESC_CACHE_INIT_DONE_SHIFT); } void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h index 0c37abbabca54197caec421422c2e60ce3303f5e..c3ee278c3747c3635ab4035affe96b0addb6dc3b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h @@ -313,8 +313,11 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_pkt_buff_size_per_tc, u32 buffer); -/* set rdm rx dma descriptor cache init */ -void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init); +/* toggle rdm rx dma descriptor cache init */ +void hw_atl_rdm_rx_dma_desc_cache_init_tgl(struct aq_hw_s *aq_hw); + +/* get rdm rx dma descriptor cache init done */ +u32 hw_atl_rdm_rx_dma_desc_cache_init_done_get(struct aq_hw_s *aq_hw); /* set rx xoff enable (per tc) */ void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h index c3febcdfa92e519405e78ec360e18ff59017e00b..35887ad89025aa992ec16dc149e5ff0c12abd888 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h @@ -318,6 +318,25 @@ /* default value of bitfield rdm_desc_init_i */ #define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_DEFAULT 0x0 +/* rdm_desc_init_done_i bitfield definitions + * preprocessor definitions for the bitfield rdm_desc_init_done_i. + * port="pif_rdm_desc_init_done_i" + */ + +/* register address for bitfield rdm_desc_init_done_i */ +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_ADR 0x00005a10 +/* bitmask for bitfield rdm_desc_init_done_i */ +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSK 0x00000001U +/* inverted bitmask for bitfield rdm_desc_init_done_i */ +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_MSKN 0xfffffffe +/* lower bit position of bitfield rdm_desc_init_done_i */ +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_SHIFT 0U +/* width of bitfield rdm_desc_init_done_i */ +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_WIDTH 1 +/* default value of bitfield rdm_desc_init_done_i */ +#define RDM_RX_DMA_DESC_CACHE_INIT_DONE_DEFAULT 0x0 + + /* rx int_desc_wrb_en bitfield definitions * preprocessor definitions for the bitfield "int_desc_wrb_en". * port="pif_rdm_int_desc_wrb_en_i" diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c index da726489e3c8debbe6c93fdb20d9006314c63a39..7bc51f8d6f2fcd0c0016e1cc6c3f8c04247455b7 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -337,7 +337,7 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) /* Convert PHY temperature from 1/256 degree Celsius * to 1/1000 degree Celsius. */ - *temp = temp_res * 1000 / 256; + *temp = (temp_res & 0xFFFF) * 1000 / 256; return 0; } diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c index 42d2e1b02c440b98971ef1f8798f84ac94f6eadf..664d664e09250ef94167485fe52914005de99e4d 100644 --- a/drivers/net/ethernet/arc/emac_rockchip.c +++ b/drivers/net/ethernet/arc/emac_rockchip.c @@ -256,6 +256,9 @@ static int emac_rockchip_remove(struct platform_device *pdev) if (priv->regulator) regulator_disable(priv->regulator); + if (priv->soc_data->need_div_macclk) + clk_disable_unprepare(priv->macclk); + free_netdev(ndev); return err; } diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index e24f5d2b6afe35477940a4a6b86c55795f855a07..53055ce5dfd61853a2be432a150f9dfd9b3af84a 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -8,7 +8,6 @@ config NET_VENDOR_BROADCOM default y depends on (SSB_POSSIBLE && HAS_DMA) || PCI || BCM63XX || \ SIBYTE_SB1xxx_SOC - select DIMLIB ---help--- If you have a network (Ethernet) chipset belonging to this class, say Y. @@ -69,6 +68,7 @@ config BCMGENET select FIXED_PHY select BCM7XXX_PHY select MDIO_BCM_UNIMAC + select DIMLIB help This driver supports the built-in Ethernet MACs found in the Broadcom BCM7xxx Set Top Box family chipset. @@ -188,6 +188,7 @@ config SYSTEMPORT select MII select PHYLIB select FIXED_PHY + select DIMLIB help This driver supports the built-in Ethernet MACs found in the Broadcom BCM7xxx Set Top Box family chipset using an internal @@ -200,6 +201,7 @@ config BNXT select LIBCRC32C select NET_DEVLINK select PAGE_POOL + select DIMLIB ---help--- This driver supports Broadcom NetXtreme-C/E 10/25/40/50 gigabit Ethernet cards. To compile this driver as a module, choose M here: diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index b4a8cf620a0c73d9b0d5e0eb0578ff1ca6d0988f..04ec909e06dfd72ec197871f8aff2701a3fc64bb 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -10382,7 +10382,8 @@ static void bnxt_cleanup_pci(struct bnxt *bp) { bnxt_unmap_bars(bp, bp->pdev); pci_release_regions(bp->pdev); - pci_disable_device(bp->pdev); + if (pci_is_enabled(bp->pdev)) + pci_disable_device(bp->pdev); } static void bnxt_init_dflt_coal(struct bnxt *bp) @@ -10669,14 +10670,11 @@ static void bnxt_fw_reset_task(struct work_struct *work) bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW; } /* fall through */ - case BNXT_FW_RESET_STATE_RESET_FW: { - u32 wait_dsecs = bp->fw_health->post_reset_wait_dsecs; - + case BNXT_FW_RESET_STATE_RESET_FW: bnxt_reset_all(bp); bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; - bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10); + bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10); return; - } case BNXT_FW_RESET_STATE_ENABLE_DEV: if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) && bp->fw_health) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index e664392dccc0e3580bdb44943b4663894f671562..7151244f8c7d2f24f4fb5ad347aadabc799cee2e 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -29,25 +29,20 @@ static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter, val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG); health_status = val & 0xffff; - if (health_status == BNXT_FW_STATUS_HEALTHY) { - rc = devlink_fmsg_string_pair_put(fmsg, "FW status", - "Healthy;"); - if (rc) - return rc; - } else if (health_status < BNXT_FW_STATUS_HEALTHY) { - rc = devlink_fmsg_string_pair_put(fmsg, "FW status", - "Not yet completed initialization;"); + if (health_status < BNXT_FW_STATUS_HEALTHY) { + rc = devlink_fmsg_string_pair_put(fmsg, "Description", + "Not yet completed initialization"); if (rc) return rc; } else if (health_status > BNXT_FW_STATUS_HEALTHY) { - rc = devlink_fmsg_string_pair_put(fmsg, "FW status", - "Encountered fatal error and cannot recover;"); + rc = devlink_fmsg_string_pair_put(fmsg, "Description", + "Encountered fatal error and cannot recover"); if (rc) return rc; } if (val >> 16) { - rc = devlink_fmsg_u32_pair_put(fmsg, "Error", val >> 16); + rc = devlink_fmsg_u32_pair_put(fmsg, "Error code", val >> 16); if (rc) return rc; } @@ -215,25 +210,68 @@ enum bnxt_dl_param_id { static const struct bnxt_dl_nvm_param nvm_params[] = { {DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV, - BNXT_NVM_SHARED_CFG, 1}, + BNXT_NVM_SHARED_CFG, 1, 1}, {DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI, - BNXT_NVM_SHARED_CFG, 1}, + BNXT_NVM_SHARED_CFG, 1, 1}, {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, - NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10}, + NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4}, {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, - NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7}, + NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4}, {BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK, - BNXT_NVM_SHARED_CFG, 1}, + BNXT_NVM_SHARED_CFG, 1, 1}, }; +union bnxt_nvm_data { + u8 val8; + __le32 val32; +}; + +static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst, + union devlink_param_value *src, + int nvm_num_bits, int dl_num_bytes) +{ + u32 val32 = 0; + + if (nvm_num_bits == 1) { + dst->val8 = src->vbool; + return; + } + if (dl_num_bytes == 4) + val32 = src->vu32; + else if (dl_num_bytes == 2) + val32 = (u32)src->vu16; + else if (dl_num_bytes == 1) + val32 = (u32)src->vu8; + dst->val32 = cpu_to_le32(val32); +} + +static void bnxt_copy_from_nvm_data(union devlink_param_value *dst, + union bnxt_nvm_data *src, + int nvm_num_bits, int dl_num_bytes) +{ + u32 val32; + + if (nvm_num_bits == 1) { + dst->vbool = src->val8; + return; + } + val32 = le32_to_cpu(src->val32); + if (dl_num_bytes == 4) + dst->vu32 = val32; + else if (dl_num_bytes == 2) + dst->vu16 = (u16)val32; + else if (dl_num_bytes == 1) + dst->vu8 = (u8)val32; +} + static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, int msg_len, union devlink_param_value *val) { struct hwrm_nvm_get_variable_input *req = msg; - void *data_addr = NULL, *buf = NULL; struct bnxt_dl_nvm_param nvm_param; - int bytesize, idx = 0, rc, i; + union bnxt_nvm_data *data; dma_addr_t data_dma_addr; + int idx = 0, rc, i; /* Get/Set NVM CFG parameter is supported only on PFs */ if (BNXT_VF(bp)) @@ -254,47 +292,31 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG) idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID; - bytesize = roundup(nvm_param.num_bits, BITS_PER_BYTE) / BITS_PER_BYTE; - switch (bytesize) { - case 1: - if (nvm_param.num_bits == 1) - buf = &val->vbool; - else - buf = &val->vu8; - break; - case 2: - buf = &val->vu16; - break; - case 4: - buf = &val->vu32; - break; - default: - return -EFAULT; - } - - data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize, - &data_dma_addr, GFP_KERNEL); - if (!data_addr) + data = dma_alloc_coherent(&bp->pdev->dev, sizeof(*data), + &data_dma_addr, GFP_KERNEL); + if (!data) return -ENOMEM; req->dest_data_addr = cpu_to_le64(data_dma_addr); - req->data_len = cpu_to_le16(nvm_param.num_bits); + req->data_len = cpu_to_le16(nvm_param.nvm_num_bits); req->option_num = cpu_to_le16(nvm_param.offset); req->index_0 = cpu_to_le16(idx); if (idx) req->dimensions = cpu_to_le16(1); if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) { - memcpy(data_addr, buf, bytesize); + bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits, + nvm_param.dl_num_bytes); rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT); } else { rc = hwrm_send_message_silent(bp, msg, msg_len, HWRM_CMD_TIMEOUT); + if (!rc) + bnxt_copy_from_nvm_data(val, data, + nvm_param.nvm_num_bits, + nvm_param.dl_num_bytes); } - if (!rc && req->req_type == cpu_to_le16(HWRM_NVM_GET_VARIABLE)) - memcpy(buf, data_addr, bytesize); - - dma_free_coherent(&bp->pdev->dev, bytesize, data_addr, data_dma_addr); + dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr); if (rc == -EACCES) netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n"); return rc; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h index b97e0baeb42d6b2a07d9af7770e551429b90df1b..2f4fd0a7d04bfae168cc9aefc6e0faac0eacd7e4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h @@ -52,7 +52,8 @@ struct bnxt_dl_nvm_param { u16 id; u16 offset; u16 dir_type; - u16 num_bits; + u16 nvm_num_bits; + u8 dl_num_bytes; }; void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 12cb77ef1081b6df50c0328eee989827bce8e5a2..0f138280315a82f753de8b1243a8ef2331228a31 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2018,6 +2018,8 @@ static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv) */ if (priv->internal_phy) { int0_enable |= UMAC_IRQ_LINK_EVENT; + if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv)) + int0_enable |= UMAC_IRQ_PHY_DET_R; } else if (priv->ext_phy) { int0_enable |= UMAC_IRQ_LINK_EVENT; } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { @@ -2611,11 +2613,14 @@ static void bcmgenet_irq_task(struct work_struct *work) priv->irq0_stat = 0; spin_unlock_irq(&priv->lock); + if (status & UMAC_IRQ_PHY_DET_R && + priv->dev->phydev->autoneg != AUTONEG_ENABLE) + phy_init_hw(priv->dev->phydev); + /* Link UP/DOWN event */ - if (status & UMAC_IRQ_LINK_EVENT) { - priv->dev->phydev->link = !!(status & UMAC_IRQ_LINK_UP); + if (status & UMAC_IRQ_LINK_EVENT) phy_mac_interrupt(priv->dev->phydev); - } + } /* bcmgenet_isr1: handle Rx and Tx priority queues */ @@ -2710,7 +2715,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) } /* all other interested interrupts handled in bottom half */ - status &= UMAC_IRQ_LINK_EVENT; + status &= (UMAC_IRQ_LINK_EVENT | UMAC_IRQ_PHY_DET_R); if (status) { /* Save irq status for bottom-half processing. */ spin_lock_irqsave(&priv->lock, flags); @@ -2874,6 +2879,12 @@ static int bcmgenet_open(struct net_device *dev) if (priv->internal_phy) bcmgenet_power_up(priv, GENET_POWER_PASSIVE); + ret = bcmgenet_mii_connect(dev); + if (ret) { + netdev_err(dev, "failed to connect to PHY\n"); + goto err_clk_disable; + } + /* take MAC out of reset */ bcmgenet_umac_reset(priv); @@ -2883,6 +2894,12 @@ static int bcmgenet_open(struct net_device *dev) reg = bcmgenet_umac_readl(priv, UMAC_CMD); priv->crc_fwd_en = !!(reg & CMD_CRC_FWD); + ret = bcmgenet_mii_config(dev, true); + if (ret) { + netdev_err(dev, "unsupported PHY\n"); + goto err_disconnect_phy; + } + bcmgenet_set_hw_addr(priv, dev->dev_addr); if (priv->internal_phy) { @@ -2898,7 +2915,7 @@ static int bcmgenet_open(struct net_device *dev) ret = bcmgenet_init_dma(priv); if (ret) { netdev_err(dev, "failed to initialize DMA\n"); - goto err_clk_disable; + goto err_disconnect_phy; } /* Always enable ring 16 - descriptor ring */ @@ -2921,25 +2938,19 @@ static int bcmgenet_open(struct net_device *dev) goto err_irq0; } - ret = bcmgenet_mii_probe(dev); - if (ret) { - netdev_err(dev, "failed to connect to PHY\n"); - goto err_irq1; - } - bcmgenet_netif_start(dev); netif_tx_start_all_queues(dev); return 0; -err_irq1: - free_irq(priv->irq1, priv); err_irq0: free_irq(priv->irq0, priv); err_fini_dma: bcmgenet_dma_teardown(priv); bcmgenet_fini_dma(priv); +err_disconnect_phy: + phy_disconnect(dev->phydev); err_clk_disable: if (priv->internal_phy) bcmgenet_power_down(priv, GENET_POWER_PASSIVE); @@ -3620,6 +3631,8 @@ static int bcmgenet_resume(struct device *d) if (priv->internal_phy) bcmgenet_power_up(priv, GENET_POWER_PASSIVE); + phy_init_hw(dev->phydev); + bcmgenet_umac_reset(priv); init_umac(priv); @@ -3628,8 +3641,6 @@ static int bcmgenet_resume(struct device *d) if (priv->wolopts) clk_disable_unprepare(priv->clk_wol); - phy_init_hw(dev->phydev); - /* Speed settings must be restored */ bcmgenet_mii_config(priv->dev, false); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 4a8fc03d82fd4676731f6fb93c89d22c799fc64c..7fbf573d8d52a8ff45c1399ece76a3808490c624 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -366,6 +366,7 @@ struct bcmgenet_mib_counters { #define EXT_PWR_DOWN_PHY_EN (1 << 20) #define EXT_RGMII_OOB_CTRL 0x0C +#define RGMII_MODE_EN_V123 (1 << 0) #define RGMII_LINK (1 << 4) #define OOB_DISABLE (1 << 5) #define RGMII_MODE_EN (1 << 6) @@ -719,8 +720,8 @@ GENET_IO_MACRO(rbuf, GENET_RBUF_OFF); /* MDIO routines */ int bcmgenet_mii_init(struct net_device *dev); +int bcmgenet_mii_connect(struct net_device *dev); int bcmgenet_mii_config(struct net_device *dev, bool init); -int bcmgenet_mii_probe(struct net_device *dev); void bcmgenet_mii_exit(struct net_device *dev); void bcmgenet_phy_power_set(struct net_device *dev, bool enable); void bcmgenet_mii_setup(struct net_device *dev); diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 970e478a9017f8ef6437870c5601f9942bd44f29..17bb8d60a157cb4da2a792521c9bcb8aa97b851d 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -173,6 +173,46 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) bcmgenet_fixed_phy_link_update); } +int bcmgenet_mii_connect(struct net_device *dev) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + struct device_node *dn = priv->pdev->dev.of_node; + struct phy_device *phydev; + u32 phy_flags = 0; + int ret; + + /* Communicate the integrated PHY revision */ + if (priv->internal_phy) + phy_flags = priv->gphy_rev; + + /* Initialize link state variables that bcmgenet_mii_setup() uses */ + priv->old_link = -1; + priv->old_speed = -1; + priv->old_duplex = -1; + priv->old_pause = -1; + + if (dn) { + phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, + phy_flags, priv->phy_interface); + if (!phydev) { + pr_err("could not attach to PHY\n"); + return -ENODEV; + } + } else { + phydev = dev->phydev; + phydev->dev_flags = phy_flags; + + ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup, + priv->phy_interface); + if (ret) { + pr_err("could not attach to PHY\n"); + return -ENODEV; + } + } + + return 0; +} + int bcmgenet_mii_config(struct net_device *dev, bool init) { struct bcmgenet_priv *priv = netdev_priv(dev); @@ -258,74 +298,29 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) */ if (priv->ext_phy) { reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); - reg |= RGMII_MODE_EN | id_mode_dis; + reg |= id_mode_dis; + if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv)) + reg |= RGMII_MODE_EN_V123; + else + reg |= RGMII_MODE_EN; bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); } - if (init) - dev_info(kdev, "configuring instance for %s\n", phy_name); - - return 0; -} - -int bcmgenet_mii_probe(struct net_device *dev) -{ - struct bcmgenet_priv *priv = netdev_priv(dev); - struct device_node *dn = priv->pdev->dev.of_node; - struct phy_device *phydev; - u32 phy_flags; - int ret; - - /* Communicate the integrated PHY revision */ - phy_flags = priv->gphy_rev; - - /* Initialize link state variables that bcmgenet_mii_setup() uses */ - priv->old_link = -1; - priv->old_speed = -1; - priv->old_duplex = -1; - priv->old_pause = -1; - - if (dn) { - phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, - phy_flags, priv->phy_interface); - if (!phydev) { - pr_err("could not attach to PHY\n"); - return -ENODEV; - } - } else { - phydev = dev->phydev; - phydev->dev_flags = phy_flags; + if (init) { + linkmode_copy(phydev->advertising, phydev->supported); - ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup, - priv->phy_interface); - if (ret) { - pr_err("could not attach to PHY\n"); - return -ENODEV; - } - } + /* The internal PHY has its link interrupts routed to the + * Ethernet MAC ISRs. On GENETv5 there is a hardware issue + * that prevents the signaling of link UP interrupts when + * the link operates at 10Mbps, so fallback to polling for + * those versions of GENET. + */ + if (priv->internal_phy && !GENET_IS_V5(priv)) + phydev->irq = PHY_IGNORE_INTERRUPT; - /* Configure port multiplexer based on what the probed PHY device since - * reading the 'max-speed' property determines the maximum supported - * PHY speed which is needed for bcmgenet_mii_config() to configure - * things appropriately. - */ - ret = bcmgenet_mii_config(dev, true); - if (ret) { - phy_disconnect(dev->phydev); - return ret; + dev_info(kdev, "configuring instance for %s\n", phy_name); } - linkmode_copy(phydev->advertising, phydev->supported); - - /* The internal PHY has its link interrupts routed to the - * Ethernet MAC ISRs. On GENETv5 there is a hardware issue - * that prevents the signaling of link UP interrupts when - * the link operates at 10Mbps, so fallback to polling for - * those versions of GENET. - */ - if (priv->internal_phy && !GENET_IS_V5(priv)) - dev->phydev->irq = PHY_IGNORE_INTERRUPT; - return 0; } diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 8e8d557901a970beea5287cf1ebfaa2ef1910f5b..1e1b774e19536611f54b641068bbfda9925c5601 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3405,17 +3405,17 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, return err; } - *tx_clk = devm_clk_get(&pdev->dev, "tx_clk"); + *tx_clk = devm_clk_get_optional(&pdev->dev, "tx_clk"); if (IS_ERR(*tx_clk)) - *tx_clk = NULL; + return PTR_ERR(*tx_clk); - *rx_clk = devm_clk_get(&pdev->dev, "rx_clk"); + *rx_clk = devm_clk_get_optional(&pdev->dev, "rx_clk"); if (IS_ERR(*rx_clk)) - *rx_clk = NULL; + return PTR_ERR(*rx_clk); - *tsu_clk = devm_clk_get(&pdev->dev, "tsu_clk"); + *tsu_clk = devm_clk_get_optional(&pdev->dev, "tsu_clk"); if (IS_ERR(*tsu_clk)) - *tsu_clk = NULL; + return PTR_ERR(*tsu_clk); err = clk_prepare_enable(*pclk); if (err) { diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.h b/drivers/net/ethernet/cavium/common/cavium_ptp.h index be2bafc7beeb3372f9aa5342420c3e3988d675a7..a04eccbc78e8aba124bcd5789a0e40c27ce3a230 100644 --- a/drivers/net/ethernet/cavium/common/cavium_ptp.h +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* cavium_ptp.h - PTP 1588 clock on Cavium hardware * Copyright (c) 2003-2015, 2017 Cavium, Inc. */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c index a4dead4ab0edba004db13542ad6f1073e430df02..86b528d8364c0712d8c26f684f140901463089a4 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c @@ -695,10 +695,10 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld) lld->write_cmpl_support = adap->params.write_cmpl_support; } -static void uld_attach(struct adapter *adap, unsigned int uld) +static int uld_attach(struct adapter *adap, unsigned int uld) { - void *handle; struct cxgb4_lld_info lli; + void *handle; uld_init(adap, &lli); uld_queue_init(adap, uld, &lli); @@ -708,7 +708,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) dev_warn(adap->pdev_dev, "could not attach to the %s driver, error %ld\n", adap->uld[uld].name, PTR_ERR(handle)); - return; + return PTR_ERR(handle); } adap->uld[uld].handle = handle; @@ -716,22 +716,22 @@ static void uld_attach(struct adapter *adap, unsigned int uld) if (adap->flags & CXGB4_FULL_INIT_DONE) adap->uld[uld].state_change(handle, CXGB4_STATE_UP); + + return 0; } -/** - * cxgb4_register_uld - register an upper-layer driver - * @type: the ULD type - * @p: the ULD methods +/* cxgb4_register_uld - register an upper-layer driver + * @type: the ULD type + * @p: the ULD methods * - * Registers an upper-layer driver with this driver and notifies the ULD - * about any presently available devices that support its type. Returns - * %-EBUSY if a ULD of the same type is already registered. + * Registers an upper-layer driver with this driver and notifies the ULD + * about any presently available devices that support its type. */ void cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p) { - int ret = 0; struct adapter *adap; + int ret = 0; if (type >= CXGB4_ULD_MAX) return; @@ -763,8 +763,12 @@ void cxgb4_register_uld(enum cxgb4_uld type, if (ret) goto free_irq; adap->uld[type] = *p; - uld_attach(adap, type); + ret = uld_attach(adap, type); + if (ret) + goto free_txq; continue; +free_txq: + release_sge_txq_uld(adap, type); free_irq: if (adap->flags & CXGB4_FULL_INIT_DONE) quiesce_rx_uld(adap, type); diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index b3da81e90132fd74d26b007ca5414a066547774f..928bfea5457bb2856e0781872e524476afec96cb 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -3791,15 +3791,11 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, * write the CIDX Updates into the Status Page at the end of the * TX Queue. */ - c.autoequiqe_to_viid = htonl((dbqt - ? FW_EQ_ETH_CMD_AUTOEQUIQE_F - : FW_EQ_ETH_CMD_AUTOEQUEQE_F) | + c.autoequiqe_to_viid = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE_F | FW_EQ_ETH_CMD_VIID_V(pi->viid)); c.fetchszm_to_iqid = - htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(dbqt - ? HOSTFCMODE_INGRESS_QUEUE_X - : HOSTFCMODE_STATUS_PAGE_X) | + htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(HOSTFCMODE_STATUS_PAGE_X) | FW_EQ_ETH_CMD_PCIECHN_V(pi->tx_chan) | FW_EQ_ETH_CMD_FETCHRO_F | FW_EQ_ETH_CMD_IQID_V(iqid)); diff --git a/drivers/net/ethernet/cortina/gemini.h b/drivers/net/ethernet/cortina/gemini.h index 0b12f89bf89a313f574f8e8a7295dbc112bcdeab..9fdf77d5eb3740982c28f5758b595aec33dbf692 100644 --- a/drivers/net/ethernet/cortina/gemini.h +++ b/drivers/net/ethernet/cortina/gemini.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* Register definitions for Gemini GMAC Ethernet device driver * * Copyright (C) 2006 Storlink, Corp. diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 9b7af94a40bb028414a178c1cc7f77daa125f3e5..96e9565f1e08a165ac48705265d93259d58b1060 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -727,6 +727,18 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb, */ nfrags = skb_shinfo(skb)->nr_frags; + /* Setup HW checksumming */ + csum_vlan = 0; + if (skb->ip_summed == CHECKSUM_PARTIAL && + !ftgmac100_prep_tx_csum(skb, &csum_vlan)) + goto drop; + + /* Add VLAN tag */ + if (skb_vlan_tag_present(skb)) { + csum_vlan |= FTGMAC100_TXDES1_INS_VLANTAG; + csum_vlan |= skb_vlan_tag_get(skb) & 0xffff; + } + /* Get header len */ len = skb_headlen(skb); @@ -753,19 +765,6 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb, if (nfrags == 0) f_ctl_stat |= FTGMAC100_TXDES0_LTS; txdes->txdes3 = cpu_to_le32(map); - - /* Setup HW checksumming */ - csum_vlan = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL && - !ftgmac100_prep_tx_csum(skb, &csum_vlan)) - goto drop; - - /* Add VLAN tag */ - if (skb_vlan_tag_present(skb)) { - csum_vlan |= FTGMAC100_TXDES1_INS_VLANTAG; - csum_vlan |= skb_vlan_tag_get(skb) & 0xffff; - } - txdes->txdes1 = cpu_to_le32(csum_vlan); /* Next descriptor */ diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 162d7d8fb2950c643af4c6d68d1bdafe44ffcf46..19379bae014430e3828f037dc7dfa3ea47a9a1d7 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -1235,6 +1235,8 @@ static void dpaa2_eth_set_rx_taildrop(struct dpaa2_eth_priv *priv, bool enable) priv->rx_td_enabled = enable; } +static void update_tx_fqids(struct dpaa2_eth_priv *priv); + static int link_state_update(struct dpaa2_eth_priv *priv) { struct dpni_link_state state = {0}; @@ -1261,6 +1263,7 @@ static int link_state_update(struct dpaa2_eth_priv *priv) goto out; if (state.up) { + update_tx_fqids(priv); netif_carrier_on(priv->net_dev); netif_tx_start_all_queues(priv->net_dev); } else { @@ -2533,6 +2536,47 @@ static int set_pause(struct dpaa2_eth_priv *priv) return 0; } +static void update_tx_fqids(struct dpaa2_eth_priv *priv) +{ + struct dpni_queue_id qid = {0}; + struct dpaa2_eth_fq *fq; + struct dpni_queue queue; + int i, j, err; + + /* We only use Tx FQIDs for FQID-based enqueue, so check + * if DPNI version supports it before updating FQIDs + */ + if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_ENQUEUE_FQID_VER_MAJOR, + DPNI_ENQUEUE_FQID_VER_MINOR) < 0) + return; + + for (i = 0; i < priv->num_fqs; i++) { + fq = &priv->fq[i]; + if (fq->type != DPAA2_TX_CONF_FQ) + continue; + for (j = 0; j < dpaa2_eth_tc_count(priv); j++) { + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token, + DPNI_QUEUE_TX, j, fq->flowid, + &queue, &qid); + if (err) + goto out_err; + + fq->tx_fqid[j] = qid.fqid; + if (fq->tx_fqid[j] == 0) + goto out_err; + } + } + + priv->enqueue = dpaa2_eth_enqueue_fq; + + return; + +out_err: + netdev_info(priv->net_dev, + "Error reading Tx FQID, fallback to QDID-based enqueue\n"); + priv->enqueue = dpaa2_eth_enqueue_qd; +} + /* Configure the DPNI object this interface is associated with */ static int setup_dpni(struct fsl_mc_device *ls_dev) { @@ -3306,6 +3350,9 @@ static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg) if (status & DPNI_IRQ_EVENT_LINK_CHANGED) link_state_update(netdev_priv(net_dev)); + if (status & DPNI_IRQ_EVENT_ENDPOINT_CHANGED) + set_mac_addr(netdev_priv(net_dev)); + return IRQ_HANDLED; } @@ -3331,7 +3378,8 @@ static int setup_irqs(struct fsl_mc_device *ls_dev) } err = dpni_set_irq_mask(ls_dev->mc_io, 0, ls_dev->mc_handle, - DPNI_IRQ_INDEX, DPNI_IRQ_EVENT_LINK_CHANGED); + DPNI_IRQ_INDEX, DPNI_IRQ_EVENT_LINK_CHANGED | + DPNI_IRQ_EVENT_ENDPOINT_CHANGED); if (err < 0) { dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d\n", err); goto free_irq; diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.h index ff2e177395d49498cfefccb08314b8b98697e568..df2458a5e9ef5b0a444cccee404a89993d3c747e 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2018 NXP */ diff --git a/drivers/net/ethernet/freescale/dpaa2/dpni.h b/drivers/net/ethernet/freescale/dpaa2/dpni.h index fd583911b6c020ad026fe79eb3a820231b92b265..ee0711d06b3a78b0cdac507fa3b3e52feda0997c 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpni.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpni.h @@ -133,9 +133,12 @@ int dpni_reset(struct fsl_mc_io *mc_io, */ #define DPNI_IRQ_INDEX 0 /** - * IRQ event - indicates a change in link state + * IRQ events: + * indicates a change in link state + * indicates a change in endpoint */ #define DPNI_IRQ_EVENT_LINK_CHANGED 0x00000001 +#define DPNI_IRQ_EVENT_ENDPOINT_CHANGED 0x00000002 int dpni_set_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, diff --git a/drivers/net/ethernet/freescale/dpaa2/dprtc-cmd.h b/drivers/net/ethernet/freescale/dpaa2/dprtc-cmd.h index 720cd50f5895ce77818fedd256ced50bbb1ab3cb..4ac05bfef338098b2bba5f1c697b36f816107ce8 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dprtc-cmd.h +++ b/drivers/net/ethernet/freescale/dpaa2/dprtc-cmd.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2013-2016 Freescale Semiconductor Inc. * Copyright 2016-2018 NXP diff --git a/drivers/net/ethernet/freescale/dpaa2/dprtc.h b/drivers/net/ethernet/freescale/dpaa2/dprtc.h index be7914c1634dfcb2ba8658506ce6c504f0a36bc7..311c184e1aef675f02ea14892225ce0947d3baee 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dprtc.h +++ b/drivers/net/ethernet/freescale/dpaa2/dprtc.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2013-2016 Freescale Semiconductor Inc. * Copyright 2016-2018 NXP diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index d4d4c72adf498e78ef8de5af9e6eb76e83ae4c4d..22c01b224baa8b500863e982373f04e09168c0ac 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3558,7 +3558,7 @@ fec_probe(struct platform_device *pdev) for (i = 0; i < irq_cnt; i++) { snprintf(irq_name, sizeof(irq_name), "int%d", i); - irq = platform_get_irq_byname(pdev, irq_name); + irq = platform_get_irq_byname_optional(pdev, irq_name); if (irq < 0) irq = platform_get_irq(pdev, i); if (irq < 0) { diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 19e2365be7d8fa19020aa687608d26441329df30..945643c026155f83fcb38ecfac40d7ef37c2d888 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -600,9 +600,9 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx) INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep); - irq = platform_get_irq_byname(pdev, "pps"); + irq = platform_get_irq_byname_optional(pdev, "pps"); if (irq < 0) - irq = platform_get_irq(pdev, irq_idx); + irq = platform_get_irq_optional(pdev, irq_idx); /* Failure to get an irq is not fatal, * only the PTP_CLOCK_PPS clock events should stop */ diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c index 59564ac99d2a6df5c589d89521b5513f78ae16fc..edec61dfc8687fff6f4867e4463753d28aab202e 100644 --- a/drivers/net/ethernet/google/gve/gve_rx.c +++ b/drivers/net/ethernet/google/gve/gve_rx.c @@ -289,6 +289,8 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc, len = be16_to_cpu(rx_desc->len) - GVE_RX_PAD; page_info = &rx->data.page_info[idx]; + dma_sync_single_for_cpu(&priv->pdev->dev, rx->data.qpl->page_buses[idx], + PAGE_SIZE, DMA_FROM_DEVICE); /* gvnic can only receive into registered segments. If the buffer * can't be recycled, our only choice is to copy the data out of diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c index 778b87b5a06c255eaff6544302aca044240814f6..0a9a7ee2a866838cce439172af87edc6ef0106e7 100644 --- a/drivers/net/ethernet/google/gve/gve_tx.c +++ b/drivers/net/ethernet/google/gve/gve_tx.c @@ -390,7 +390,21 @@ static void gve_tx_fill_seg_desc(union gve_tx_desc *seg_desc, seg_desc->seg.seg_addr = cpu_to_be64(addr); } -static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb) +static void gve_dma_sync_for_device(struct device *dev, dma_addr_t *page_buses, + u64 iov_offset, u64 iov_len) +{ + dma_addr_t dma; + u64 addr; + + for (addr = iov_offset; addr < iov_offset + iov_len; + addr += PAGE_SIZE) { + dma = page_buses[addr / PAGE_SIZE]; + dma_sync_single_for_device(dev, dma, PAGE_SIZE, DMA_TO_DEVICE); + } +} + +static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb, + struct device *dev) { int pad_bytes, hlen, hdr_nfrags, payload_nfrags, l4_hdr_offset; union gve_tx_desc *pkt_desc, *seg_desc; @@ -432,6 +446,9 @@ static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb) skb_copy_bits(skb, 0, tx->tx_fifo.base + info->iov[hdr_nfrags - 1].iov_offset, hlen); + gve_dma_sync_for_device(dev, tx->tx_fifo.qpl->page_buses, + info->iov[hdr_nfrags - 1].iov_offset, + info->iov[hdr_nfrags - 1].iov_len); copy_offset = hlen; for (i = payload_iov; i < payload_nfrags + payload_iov; i++) { @@ -445,6 +462,9 @@ static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb) skb_copy_bits(skb, copy_offset, tx->tx_fifo.base + info->iov[i].iov_offset, info->iov[i].iov_len); + gve_dma_sync_for_device(dev, tx->tx_fifo.qpl->page_buses, + info->iov[i].iov_offset, + info->iov[i].iov_len); copy_offset += info->iov[i].iov_len; } @@ -473,7 +493,7 @@ netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev) gve_tx_put_doorbell(priv, tx->q_resources, tx->req); return NETDEV_TX_BUSY; } - nsegs = gve_tx_add_skb(tx, skb); + nsegs = gve_tx_add_skb(tx, skb, &priv->pdev->dev); netdev_tx_sent_queue(tx->netdev_txq, skb->len); skb_tx_timestamp(skb); diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index c84167447abe650c36186eae40343b2584ac4fbb..4606a7e4a6d19a2471adb6cdb2f2c5f810bc8c37 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -237,6 +237,7 @@ struct hip04_priv { dma_addr_t rx_phys[RX_DESC_NUM]; unsigned int rx_head; unsigned int rx_buf_size; + unsigned int rx_cnt_remaining; struct device_node *phy_node; struct phy_device *phy; @@ -575,7 +576,6 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget) struct hip04_priv *priv = container_of(napi, struct hip04_priv, napi); struct net_device *ndev = priv->ndev; struct net_device_stats *stats = &ndev->stats; - unsigned int cnt = hip04_recv_cnt(priv); struct rx_desc *desc; struct sk_buff *skb; unsigned char *buf; @@ -588,8 +588,8 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget) /* clean up tx descriptors */ tx_remaining = hip04_tx_reclaim(ndev, false); - - while (cnt && !last) { + priv->rx_cnt_remaining += hip04_recv_cnt(priv); + while (priv->rx_cnt_remaining && !last) { buf = priv->rx_buf[priv->rx_head]; skb = build_skb(buf, priv->rx_buf_size); if (unlikely(!skb)) { @@ -635,11 +635,13 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget) hip04_set_recv_desc(priv, phys); priv->rx_head = RX_NEXT(priv->rx_head); - if (rx >= budget) + if (rx >= budget) { + --priv->rx_cnt_remaining; goto done; + } - if (--cnt == 0) - cnt = hip04_recv_cnt(priv); + if (--priv->rx_cnt_remaining == 0) + priv->rx_cnt_remaining += hip04_recv_cnt(priv); } if (!(priv->reg_inten & RCV_INT)) { @@ -724,6 +726,7 @@ static int hip04_mac_open(struct net_device *ndev) int i; priv->rx_head = 0; + priv->rx_cnt_remaining = 0; priv->tx_head = 0; priv->tx_tail = 0; hip04_reset_ppe(priv); @@ -1038,7 +1041,6 @@ static int hip04_remove(struct platform_device *pdev) hip04_free_ring(ndev, d); unregister_netdev(ndev); - free_irq(ndev->irq, ndev); of_node_put(priv->phy_node); cancel_work_sync(&priv->tx_timeout_task); free_netdev(ndev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index c4b7bf851a28bc0258b6e24acccfd8f5ddc00323..75ccc1e7076bde9a5bd681f0e6d3370f333f54db 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -32,6 +32,8 @@ #define HNAE3_MOD_VERSION "1.0" +#define HNAE3_MIN_VECTOR_NUM 2 /* first one for misc, another for IO */ + /* Device IDs */ #define HNAE3_DEV_ID_GE 0xA220 #define HNAE3_DEV_ID_25GE 0xA221 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index fd7f94372ff0dfae9d37103a8b4b8d93f7bed7aa..e02e01bd9effec698b740baa35e56a685eb325fb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -906,6 +906,9 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev) hnae3_get_field(__le16_to_cpu(req->pf_intr_vector_number), HCLGE_PF_VEC_NUM_M, HCLGE_PF_VEC_NUM_S); + /* nic's msix numbers is always equals to the roce's. */ + hdev->num_nic_msi = hdev->num_roce_msi; + /* PF should have NIC vectors and Roce vectors, * NIC vectors are queued before Roce vectors. */ @@ -915,6 +918,15 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev) hdev->num_msi = hnae3_get_field(__le16_to_cpu(req->pf_intr_vector_number), HCLGE_PF_VEC_NUM_M, HCLGE_PF_VEC_NUM_S); + + hdev->num_nic_msi = hdev->num_msi; + } + + if (hdev->num_nic_msi < HNAE3_MIN_VECTOR_NUM) { + dev_err(&hdev->pdev->dev, + "Just %u msi resources, not enough for pf(min:2).\n", + hdev->num_nic_msi); + return -EINVAL; } return 0; @@ -1507,6 +1519,10 @@ static int hclge_assign_tqp(struct hclge_vport *vport, u16 num_tqps) kinfo->rss_size = min_t(u16, hdev->rss_size_max, vport->alloc_tqps / hdev->tm_info.num_tc); + /* ensure one to one mapping between irq and queue at default */ + kinfo->rss_size = min_t(u16, kinfo->rss_size, + (hdev->num_nic_msi - 1) / hdev->tm_info.num_tc); + return 0; } @@ -2285,7 +2301,8 @@ static int hclge_init_msi(struct hclge_dev *hdev) int vectors; int i; - vectors = pci_alloc_irq_vectors(pdev, 1, hdev->num_msi, + vectors = pci_alloc_irq_vectors(pdev, HNAE3_MIN_VECTOR_NUM, + hdev->num_msi, PCI_IRQ_MSI | PCI_IRQ_MSIX); if (vectors < 0) { dev_err(&pdev->dev, @@ -2300,6 +2317,7 @@ static int hclge_init_msi(struct hclge_dev *hdev) hdev->num_msi = vectors; hdev->num_msi_left = vectors; + hdev->base_msi_vector = pdev->irq; hdev->roce_base_vector = hdev->base_msi_vector + hdev->roce_base_msix_offset; @@ -3903,6 +3921,7 @@ static int hclge_get_vector(struct hnae3_handle *handle, u16 vector_num, int alloc = 0; int i, j; + vector_num = min_t(u16, hdev->num_nic_msi - 1, vector_num); vector_num = min(hdev->num_msi_left, vector_num); for (j = 0; j < vector_num; j++) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 3e9574a9e22dcbac92ef06832ef266d3687a42f0..c3d56b872ed7342893c93a31524bf3844e1e3acf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -763,6 +763,7 @@ struct hclge_dev { u32 base_msi_vector; u16 *vector_status; int *vector_irq; + u16 num_nic_msi; /* Num of nic vectors for this PF */ u16 num_roce_msi; /* Num of roce vectors for this PF */ int roce_base_vector; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 9f0e35f277895a00898fa475e2b70c5f6f17c8b3..62399cc1c5a630c4610ce044bd8d2054f8bde1b1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -537,9 +537,16 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) kinfo->rss_size = kinfo->req_rss_size; } else if (kinfo->rss_size > max_rss_size || (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) { + /* if user not set rss, the rss_size should compare with the + * valid msi numbers to ensure one to one map between tqp and + * irq as default. + */ + if (!kinfo->req_rss_size) + max_rss_size = min_t(u16, max_rss_size, + (hdev->num_nic_msi - 1) / + kinfo->num_tc); + /* Set to the maximum specification value (max_rss_size). */ - dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n", - kinfo->rss_size, max_rss_size); kinfo->rss_size = max_rss_size; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index e3090b3dab1da412390a87cb4d417fb025489f72..7d7e712691b9216bac17925f37544f1d919bdab5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -411,6 +411,13 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) kinfo->tqp[i] = &hdev->htqp[i].q; } + /* after init the max rss_size and tqps, adjust the default tqp numbers + * and rss size with the actual vector numbers + */ + kinfo->num_tqps = min_t(u16, hdev->num_nic_msix - 1, kinfo->num_tqps); + kinfo->rss_size = min_t(u16, kinfo->num_tqps / kinfo->num_tc, + kinfo->rss_size); + return 0; } @@ -502,6 +509,7 @@ static int hclgevf_get_vector(struct hnae3_handle *handle, u16 vector_num, int alloc = 0; int i, j; + vector_num = min_t(u16, hdev->num_nic_msix - 1, vector_num); vector_num = min(hdev->num_msi_left, vector_num); for (j = 0; j < vector_num; j++) { @@ -2246,13 +2254,14 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev) int vectors; int i; - if (hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B)) + if (hnae3_dev_roce_supported(hdev)) vectors = pci_alloc_irq_vectors(pdev, hdev->roce_base_msix_offset + 1, hdev->num_msi, PCI_IRQ_MSIX); else - vectors = pci_alloc_irq_vectors(pdev, 1, hdev->num_msi, + vectors = pci_alloc_irq_vectors(pdev, HNAE3_MIN_VECTOR_NUM, + hdev->num_msi, PCI_IRQ_MSI | PCI_IRQ_MSIX); if (vectors < 0) { @@ -2268,6 +2277,7 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev) hdev->num_msi = vectors; hdev->num_msi_left = vectors; + hdev->base_msi_vector = pdev->irq; hdev->roce_base_vector = pdev->irq + hdev->roce_base_msix_offset; @@ -2533,7 +2543,7 @@ static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev) req = (struct hclgevf_query_res_cmd *)desc.data; - if (hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B)) { + if (hnae3_dev_roce_supported(hdev)) { hdev->roce_base_msix_offset = hnae3_get_field(__le16_to_cpu(req->msixcap_localid_ba_rocee), HCLGEVF_MSIX_OFT_ROCEE_M, @@ -2542,6 +2552,9 @@ static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev) hnae3_get_field(__le16_to_cpu(req->vf_intr_vector_number), HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S); + /* nic's msix numbers is always equals to the roce's. */ + hdev->num_nic_msix = hdev->num_roce_msix; + /* VF should have NIC vectors and Roce vectors, NIC vectors * are queued before Roce vectors. The offset is fixed to 64. */ @@ -2551,6 +2564,15 @@ static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev) hdev->num_msi = hnae3_get_field(__le16_to_cpu(req->vf_intr_vector_number), HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S); + + hdev->num_nic_msix = hdev->num_msi; + } + + if (hdev->num_nic_msix < HNAE3_MIN_VECTOR_NUM) { + dev_err(&hdev->pdev->dev, + "Just %u msi resources, not enough for vf(min:2).\n", + hdev->num_nic_msix); + return -EINVAL; } return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index bdde3afc286b24996a8fc999a661269011d60047..2b8d6bc6d2245fede21d72c46329ffb275019202 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -270,6 +270,7 @@ struct hclgevf_dev { u16 num_msi; u16 num_msi_left; u16 num_msi_used; + u16 num_nic_msix; /* Num of nic vectors for this VF */ u16 num_roce_msix; /* Num of roce vectors for this VF */ u16 roce_base_msix_offset; int roce_base_vector; diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c index 211c5f74b4c86682e817c7aee4748284b600594f..aec7e98bcc853a796e2f107768726907d70f9cec 100644 --- a/drivers/net/ethernet/i825xx/lasi_82596.c +++ b/drivers/net/ethernet/i825xx/lasi_82596.c @@ -96,6 +96,8 @@ #define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */ +#define LIB82596_DMA_ATTR DMA_ATTR_NON_CONSISTENT + #define DMA_WBACK(ndev, addr, len) \ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0) @@ -200,7 +202,7 @@ static int __exit lan_remove_chip(struct parisc_device *pdev) unregister_netdev (dev); dma_free_attrs(&pdev->dev, sizeof(struct i596_private), lp->dma, - lp->dma_addr, DMA_ATTR_NON_CONSISTENT); + lp->dma_addr, LIB82596_DMA_ATTR); free_netdev (dev); return 0; } diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c index 1274ad24d6af19dca829fcb4b241b0bb5fb17e0f..f9742af7f142d97a111318d7ca10cdf120ce2c72 100644 --- a/drivers/net/ethernet/i825xx/lib82596.c +++ b/drivers/net/ethernet/i825xx/lib82596.c @@ -1065,7 +1065,7 @@ static int i82596_probe(struct net_device *dev) dma = dma_alloc_attrs(dev->dev.parent, sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL, - DMA_ATTR_NON_CONSISTENT); + LIB82596_DMA_ATTR); if (!dma) { printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__); return -ENOMEM; @@ -1087,7 +1087,7 @@ static int i82596_probe(struct net_device *dev) i = register_netdev(dev); if (i) { dma_free_attrs(dev->dev.parent, sizeof(struct i596_dma), - dma, lp->dma_addr, DMA_ATTR_NON_CONSISTENT); + dma, lp->dma_addr, LIB82596_DMA_ATTR); return i; } diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c index 6eb6c2ff7f099230c0416d09e4bb715c8628170b..6436a98c5953fcd92ad37e1436e784b53b39c709 100644 --- a/drivers/net/ethernet/i825xx/sni_82596.c +++ b/drivers/net/ethernet/i825xx/sni_82596.c @@ -24,6 +24,8 @@ static const char sni_82596_string[] = "snirm_82596"; +#define LIB82596_DMA_ATTR 0 + #define DMA_WBACK(priv, addr, len) do { } while (0) #define DMA_INV(priv, addr, len) do { } while (0) #define DMA_WBACK_INV(priv, addr, len) do { } while (0) @@ -152,7 +154,7 @@ static int sni_82596_driver_remove(struct platform_device *pdev) unregister_netdev(dev); dma_free_attrs(dev->dev.parent, sizeof(struct i596_private), lp->dma, - lp->dma_addr, DMA_ATTR_NON_CONSISTENT); + lp->dma_addr, LIB82596_DMA_ATTR); iounmap(lp->ca); iounmap(lp->mpu_port); free_netdev (dev); diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 2b073a3c0b8474370e1ac072548bd68d0e4f7471..f59d9a8e35e2e7343cd31f017dc3e8fd5f958b96 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2878,12 +2878,10 @@ static int enable_scrq_irq(struct ibmvnic_adapter *adapter, if (test_bit(0, &adapter->resetting) && adapter->reset_reason == VNIC_RESET_MOBILITY) { - u64 val = (0xff000000) | scrq->hw_irq; + struct irq_desc *desc = irq_to_desc(scrq->irq); + struct irq_chip *chip = irq_desc_get_chip(desc); - rc = plpar_hcall_norets(H_EOI, val); - if (rc) - dev_err(dev, "H_EOI FAILED irq 0x%llx. rc=%ld\n", - val, rc); + chip->irq_eoi(&desc->irq_data); } rc = plpar_hcall_norets(H_VIOCTL, adapter->vdev->unit_address, diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index 71d3d8854d8f124293399e5ac23aae6f328593fb..be56e631d693884a40568effdda9b2aa1bf2696d 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -607,6 +607,7 @@ static int e1000_set_ringparam(struct net_device *netdev, for (i = 0; i < adapter->num_rx_queues; i++) rxdr[i].count = rxdr->count; + err = 0; if (netif_running(adapter->netdev)) { /* Try to get new resources before deleting old */ err = e1000_setup_all_rx_resources(adapter); @@ -627,14 +628,13 @@ static int e1000_set_ringparam(struct net_device *netdev, adapter->rx_ring = rxdr; adapter->tx_ring = txdr; err = e1000_up(adapter); - if (err) - goto err_setup; } kfree(tx_old); kfree(rx_old); clear_bit(__E1000_RESETTING, &adapter->flags); - return 0; + return err; + err_setup_tx: e1000_free_all_rx_resources(adapter); err_setup_rx: @@ -646,7 +646,6 @@ static int e1000_set_ringparam(struct net_device *netdev, err_alloc_tx: if (netif_running(adapter->netdev)) e1000_up(adapter); -err_setup: clear_bit(__E1000_RESETTING, &adapter->flags); return err; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index b1c3227ae4ab8b923af7ef270403a37a47e35a69..a05dfecdd9b4bda601667455255fd84b50e2b73a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -157,11 +157,6 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid) err = i40e_queue_pair_enable(vsi, qid); if (err) return err; - - /* Kick start the NAPI context so that receiving will start */ - err = i40e_xsk_wakeup(vsi->netdev, qid, XDP_WAKEUP_RX); - if (err) - return err; } return 0; diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 3ec2ce0725d536f2a2110f551e7f80371aaaf798..8a6ef351412921c729db50e686201b51ff4795ec 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -466,7 +466,7 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw) ? igb_setup_copper_link_82575 : igb_setup_serdes_link_82575; - if (mac->type == e1000_82580) { + if (mac->type == e1000_82580 || mac->type == e1000_i350) { switch (hw->device_id) { /* feature not supported on these id's */ case E1000_DEV_ID_DH89XXCC_SGMII: diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 105b0624081a12bb6d375247856aacfa43bb6bd6..9148c62d9ac5ec03e10bd308bcc331663ea5729d 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -753,7 +753,8 @@ u32 igb_rd32(struct e1000_hw *hw, u32 reg) struct net_device *netdev = igb->netdev; hw->hw_addr = NULL; netdev_err(netdev, "PCIe link lost\n"); - WARN(1, "igb: Failed to read reg 0x%x!\n", reg); + WARN(pci_device_is_present(igb->pdev), + "igb: Failed to read reg 0x%x!\n", reg); } return value; @@ -2064,7 +2065,8 @@ static void igb_check_swap_media(struct igb_adapter *adapter) if ((hw->phy.media_type == e1000_media_type_copper) && (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) { swap_now = true; - } else if (!(connsw & E1000_CONNSW_SERDESD)) { + } else if ((hw->phy.media_type != e1000_media_type_copper) && + !(connsw & E1000_CONNSW_SERDESD)) { /* copper signal takes time to appear */ if (adapter->copper_tries < 4) { adapter->copper_tries++; @@ -2370,7 +2372,7 @@ void igb_reset(struct igb_adapter *adapter) adapter->ei.get_invariants(hw); adapter->flags &= ~IGB_FLAG_MEDIA_RESET; } - if ((mac->type == e1000_82575) && + if ((mac->type == e1000_82575 || mac->type == e1000_i350) && (adapter->flags & IGB_FLAG_MAS_ENABLE)) { igb_enable_mas(adapter); } diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 63b62d74f9610c744fbd7f6c0a1e2e768291dc19..8e424dfab12ea9eb20a88c35504923fc89a06f6a 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -4047,7 +4047,8 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg) hw->hw_addr = NULL; netif_device_detach(netdev); netdev_err(netdev, "PCIe link lost, device now detached\n"); - WARN(1, "igc: Failed to read reg 0x%x!\n", reg); + WARN(pci_device_is_present(igc->pdev), + "igc: Failed to read reg 0x%x!\n", reg); } return value; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 1ce2397306b9261826a736396ff5600fb6a115ec..91b3780ddb040de656e46a234f5c58e9b4fd71f2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4310,7 +4310,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) if (test_bit(__IXGBE_RX_FCOE, &rx_ring->state)) set_bit(__IXGBE_RX_3K_BUFFER, &rx_ring->state); - clear_bit(__IXGBE_RX_BUILD_SKB_ENABLED, &rx_ring->state); if (adapter->flags2 & IXGBE_FLAG2_RX_LEGACY) continue; diff --git a/drivers/net/ethernet/marvell/mvneta_bm.h b/drivers/net/ethernet/marvell/mvneta_bm.h index c8425d35c049bc8cf232eee65731ea0b166227cc..e47783ce77e08de2b935a983dc0c6bf782e0d5d9 100644 --- a/drivers/net/ethernet/marvell/mvneta_bm.h +++ b/drivers/net/ethernet/marvell/mvneta_bm.h @@ -160,16 +160,23 @@ static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv, (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS)); } #else -void mvneta_bm_pool_destroy(struct mvneta_bm *priv, - struct mvneta_bm_pool *bm_pool, u8 port_map) {} -void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, - u8 port_map) {} -int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf) { return 0; } -int mvneta_bm_pool_refill(struct mvneta_bm *priv, - struct mvneta_bm_pool *bm_pool) {return 0; } -struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id, - enum mvneta_bm_type type, u8 port_id, - int pkt_size) { return NULL; } +static inline void mvneta_bm_pool_destroy(struct mvneta_bm *priv, + struct mvneta_bm_pool *bm_pool, + u8 port_map) {} +static inline void mvneta_bm_bufs_free(struct mvneta_bm *priv, + struct mvneta_bm_pool *bm_pool, + u8 port_map) {} +static inline int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf) +{ return 0; } +static inline int mvneta_bm_pool_refill(struct mvneta_bm *priv, + struct mvneta_bm_pool *bm_pool) +{ return 0; } +static inline struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, + u8 pool_id, + enum mvneta_bm_type type, + u8 port_id, + int pkt_size) +{ return NULL; } static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, @@ -178,7 +185,8 @@ static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv, static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool) { return 0; } -struct mvneta_bm *mvneta_bm_get(struct device_node *node) { return NULL; } -void mvneta_bm_put(struct mvneta_bm *priv) {} +static inline struct mvneta_bm *mvneta_bm_get(struct device_node *node) +{ return NULL; } +static inline void mvneta_bm_put(struct mvneta_bm *priv) {} #endif /* CONFIG_MVNETA_BM */ #endif diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index c61069340f4f23a26b825ab2a304e69fdbaddbba..703adb96429e24abe453e681f6f815ba1fb526de 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -261,6 +261,7 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, ge_mode = 0; switch (state->interface) { case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_GMII: ge_mode = 1; break; case PHY_INTERFACE_MODE_REVMII: diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 4356f3a580027602b84f7d550b3b56244e757307..1187ef1375e298bc1ae309a72064308f6e382c34 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -471,12 +471,31 @@ void mlx4_init_quotas(struct mlx4_dev *dev) priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf]; } -static int get_max_gauranteed_vfs_counter(struct mlx4_dev *dev) +static int +mlx4_calc_res_counter_guaranteed(struct mlx4_dev *dev, + struct resource_allocator *res_alloc, + int vf) { - /* reduce the sink counter */ - return (dev->caps.max_counters - 1 - - (MLX4_PF_COUNTERS_PER_PORT * MLX4_MAX_PORTS)) - / MLX4_MAX_PORTS; + struct mlx4_active_ports actv_ports; + int ports, counters_guaranteed; + + /* For master, only allocate according to the number of phys ports */ + if (vf == mlx4_master_func_num(dev)) + return MLX4_PF_COUNTERS_PER_PORT * dev->caps.num_ports; + + /* calculate real number of ports for the VF */ + actv_ports = mlx4_get_active_ports(dev, vf); + ports = bitmap_weight(actv_ports.ports, dev->caps.num_ports); + counters_guaranteed = ports * MLX4_VF_COUNTERS_PER_PORT; + + /* If we do not have enough counters for this VF, do not + * allocate any for it. '-1' to reduce the sink counter. + */ + if ((res_alloc->res_reserved + counters_guaranteed) > + (dev->caps.max_counters - 1)) + return 0; + + return counters_guaranteed; } int mlx4_init_resource_tracker(struct mlx4_dev *dev) @@ -484,7 +503,6 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int i, j; int t; - int max_vfs_guarantee_counter = get_max_gauranteed_vfs_counter(dev); priv->mfunc.master.res_tracker.slave_list = kcalloc(dev->num_slaves, sizeof(struct slave_list), @@ -603,16 +621,8 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev) break; case RES_COUNTER: res_alloc->quota[t] = dev->caps.max_counters; - if (t == mlx4_master_func_num(dev)) - res_alloc->guaranteed[t] = - MLX4_PF_COUNTERS_PER_PORT * - MLX4_MAX_PORTS; - else if (t <= max_vfs_guarantee_counter) - res_alloc->guaranteed[t] = - MLX4_VF_COUNTERS_PER_PORT * - MLX4_MAX_PORTS; - else - res_alloc->guaranteed[t] = 0; + res_alloc->guaranteed[t] = + mlx4_calc_res_counter_guaranteed(dev, res_alloc, t); break; default: break; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 8d76452cacdc0fa22135f5f42bb1f003ec7467c3..f1a7bc46f1c0c67a886e0a9ecb06f628b3bc505f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -345,7 +345,7 @@ struct mlx5e_tx_wqe_info { u8 num_wqebbs; u8 num_dma; #ifdef CONFIG_MLX5_EN_TLS - skb_frag_t *resync_dump_frag; + struct page *resync_dump_frag_page; #endif }; @@ -410,6 +410,7 @@ struct mlx5e_txqsq { struct device *pdev; __be32 mkey_be; unsigned long state; + unsigned int hw_mtu; struct hwtstamp_config *tstamp; struct mlx5_clock *clock; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c index b3a249b2a482fbd65ee6e857c572d66727d4ad45..ac44bbe95c5c1b653366252662fddb54e92188fa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c @@ -141,7 +141,7 @@ int mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv) "Failed to create hv vhca stats agent, err = %ld\n", PTR_ERR(agent)); - kfree(priv->stats_agent.buf); + kvfree(priv->stats_agent.buf); return IS_ERR_OR_NULL(agent); } @@ -157,5 +157,5 @@ void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv) return; mlx5_hv_vhca_agent_destroy(priv->stats_agent.agent); - kfree(priv->stats_agent.buf); + kvfree(priv->stats_agent.buf); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index f8ee18b4da6fa92818f515a30de826d183558475..13af72556987ffe6ffd5dbf2a32d240a1a545cc0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -97,15 +97,19 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv, if (ret) return ret; - if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET) + if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET) { + ip_rt_put(rt); return -ENETUNREACH; + } #else return -EOPNOTSUPP; #endif ret = get_route_and_out_devs(priv, rt->dst.dev, route_dev, out_dev); - if (ret < 0) + if (ret < 0) { + ip_rt_put(rt); return ret; + } if (!(*out_ttl)) *out_ttl = ip4_dst_hoplimit(&rt->dst); @@ -149,8 +153,10 @@ static int mlx5e_route_lookup_ipv6(struct mlx5e_priv *priv, *out_ttl = ip6_dst_hoplimit(dst); ret = get_route_and_out_devs(priv, dst->dev, route_dev, out_dev); - if (ret < 0) + if (ret < 0) { + dst_release(dst); return ret; + } #else return -EOPNOTSUPP; #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index 87be9674790292beceddd8908e0d52d07a71c4e1..7c8796d9743fa5a6c66f4aa3e0017b800a121a9b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -15,15 +15,14 @@ #else /* TLS offload requires additional stop_room for: * - a resync SKB. - * kTLS offload requires additional stop_room for: - * - static params WQE, - * - progress params WQE, and - * - resync DUMP per frag. + * kTLS offload requires fixed additional stop_room for: + * - a static params WQE, and a progress params WQE. + * The additional MTU-depending room for the resync DUMP WQEs + * will be calculated and added in runtime. */ #define MLX5E_SQ_TLS_ROOM \ (MLX5_SEND_WQE_MAX_WQEBBS + \ - MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS + \ - MAX_SKB_FRAGS * MLX5E_KTLS_MAX_DUMP_WQEBBS) + MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS) #endif #define INL_HDR_START_SZ (sizeof(((struct mlx5_wqe_eth_seg *)NULL)->inline_hdr.start)) @@ -92,7 +91,7 @@ mlx5e_fill_sq_frag_edge(struct mlx5e_txqsq *sq, struct mlx5_wq_cyc *wq, /* fill sq frag edge with nops to avoid wqe wrapping two pages */ for (; wi < edge_wi; wi++) { - wi->skb = NULL; + memset(wi, 0, sizeof(*wi)); wi->num_wqebbs = 1; mlx5e_post_nop(wq, sq->sqn, &sq->pc); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c index d2ff74d52720d2ba369c143f086922185117086e..46725cd743a369b6531b2dc3fd8051e2129f266e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c @@ -38,7 +38,7 @@ static int mlx5e_ktls_add(struct net_device *netdev, struct sock *sk, return -ENOMEM; tx_priv->expected_seq = start_offload_tcp_sn; - tx_priv->crypto_info = crypto_info; + tx_priv->crypto_info = *(struct tls12_crypto_info_aes_gcm_128 *)crypto_info; mlx5e_set_ktls_tx_priv_ctx(tls_ctx, tx_priv); /* tc and underlay_qpn values are not in use for tls tis */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h index b7298f9ee3d3f7d7a2adcb5cd2895d5ab2a0d78f..a3efa29a4629d796876452368502c3d10a9b12b5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h @@ -21,7 +21,14 @@ MLX5_ST_SZ_BYTES(tls_progress_params)) #define MLX5E_KTLS_PROGRESS_WQEBBS \ (DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB)) -#define MLX5E_KTLS_MAX_DUMP_WQEBBS 2 + +struct mlx5e_dump_wqe { + struct mlx5_wqe_ctrl_seg ctrl; + struct mlx5_wqe_data_seg data; +}; + +#define MLX5E_KTLS_DUMP_WQEBBS \ + (DIV_ROUND_UP(sizeof(struct mlx5e_dump_wqe), MLX5_SEND_WQE_BB)) enum { MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD = 0, @@ -37,7 +44,7 @@ enum { struct mlx5e_ktls_offload_context_tx { struct tls_offload_context_tx *tx_ctx; - struct tls_crypto_info *crypto_info; + struct tls12_crypto_info_aes_gcm_128 crypto_info; u32 expected_seq; u32 tisn; u32 key_id; @@ -86,14 +93,28 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev, struct mlx5e_tx_wqe **wqe, u16 *pi); void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq, struct mlx5e_tx_wqe_info *wi, - struct mlx5e_sq_dma *dma); - + u32 *dma_fifo_cc); +static inline u8 +mlx5e_ktls_dumps_num_wqebbs(struct mlx5e_txqsq *sq, unsigned int nfrags, + unsigned int sync_len) +{ + /* Given the MTU and sync_len, calculates an upper bound for the + * number of WQEBBs needed for the TX resync DUMP WQEs of a record. + */ + return MLX5E_KTLS_DUMP_WQEBBS * + (nfrags + DIV_ROUND_UP(sync_len, sq->hw_mtu)); +} #else static inline void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv) { } +static inline void +mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq, + struct mlx5e_tx_wqe_info *wi, + u32 *dma_fifo_cc) {} + #endif #endif /* __MLX5E_TLS_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c index d195366461c9f21df74ad755d8be36efd7708f2c..778dab1af8fc659cae40ead517bc94dc22f68a4a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c @@ -24,17 +24,12 @@ enum { static void fill_static_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx) { - struct tls_crypto_info *crypto_info = priv_tx->crypto_info; - struct tls12_crypto_info_aes_gcm_128 *info; + struct tls12_crypto_info_aes_gcm_128 *info = &priv_tx->crypto_info; char *initial_rn, *gcm_iv; u16 salt_sz, rec_seq_sz; char *salt, *rec_seq; u8 tls_version; - if (WARN_ON(crypto_info->cipher_type != TLS_CIPHER_AES_GCM_128)) - return; - - info = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info; EXTRACT_INFO_FIELDS; gcm_iv = MLX5_ADDR_OF(tls_static_params, ctx, gcm_iv); @@ -108,16 +103,15 @@ build_progress_params(struct mlx5e_tx_wqe *wqe, u16 pc, u32 sqn, } static void tx_fill_wi(struct mlx5e_txqsq *sq, - u16 pi, u8 num_wqebbs, - skb_frag_t *resync_dump_frag, - u32 num_bytes) + u16 pi, u8 num_wqebbs, u32 num_bytes, + struct page *page) { struct mlx5e_tx_wqe_info *wi = &sq->db.wqe_info[pi]; - wi->skb = NULL; - wi->num_wqebbs = num_wqebbs; - wi->resync_dump_frag = resync_dump_frag; - wi->num_bytes = num_bytes; + memset(wi, 0, sizeof(*wi)); + wi->num_wqebbs = num_wqebbs; + wi->num_bytes = num_bytes; + wi->resync_dump_frag_page = page; } void mlx5e_ktls_tx_offload_set_pending(struct mlx5e_ktls_offload_context_tx *priv_tx) @@ -145,7 +139,7 @@ post_static_params(struct mlx5e_txqsq *sq, umr_wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_STATIC_UMR_WQE_SZ, &pi); build_static_params(umr_wqe, sq->pc, sq->sqn, priv_tx, fence); - tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, NULL, 0); + tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, 0, NULL); sq->pc += MLX5E_KTLS_STATIC_WQEBBS; } @@ -159,7 +153,7 @@ post_progress_params(struct mlx5e_txqsq *sq, wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_PROGRESS_WQE_SZ, &pi); build_progress_params(wqe, sq->pc, sq->sqn, priv_tx, fence); - tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, NULL, 0); + tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, 0, NULL); sq->pc += MLX5E_KTLS_PROGRESS_WQEBBS; } @@ -169,6 +163,14 @@ mlx5e_ktls_tx_post_param_wqes(struct mlx5e_txqsq *sq, bool skip_static_post, bool fence_first_post) { bool progress_fence = skip_static_post || !fence_first_post; + struct mlx5_wq_cyc *wq = &sq->wq; + u16 contig_wqebbs_room, pi; + + pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); + contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi); + if (unlikely(contig_wqebbs_room < + MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS)) + mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room); if (!skip_static_post) post_static_params(sq, priv_tx, fence_first_post); @@ -180,29 +182,36 @@ struct tx_sync_info { u64 rcd_sn; s32 sync_len; int nr_frags; - skb_frag_t *frags[MAX_SKB_FRAGS]; + skb_frag_t frags[MAX_SKB_FRAGS]; +}; + +enum mlx5e_ktls_sync_retval { + MLX5E_KTLS_SYNC_DONE, + MLX5E_KTLS_SYNC_FAIL, + MLX5E_KTLS_SYNC_SKIP_NO_DATA, }; -static bool tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx, - u32 tcp_seq, struct tx_sync_info *info) +static enum mlx5e_ktls_sync_retval +tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx, + u32 tcp_seq, struct tx_sync_info *info) { struct tls_offload_context_tx *tx_ctx = priv_tx->tx_ctx; + enum mlx5e_ktls_sync_retval ret = MLX5E_KTLS_SYNC_DONE; struct tls_record_info *record; int remaining, i = 0; unsigned long flags; - bool ret = true; spin_lock_irqsave(&tx_ctx->lock, flags); record = tls_get_record(tx_ctx, tcp_seq, &info->rcd_sn); if (unlikely(!record)) { - ret = false; + ret = MLX5E_KTLS_SYNC_FAIL; goto out; } if (unlikely(tcp_seq < tls_record_start_seq(record))) { - if (!tls_record_is_start_marker(record)) - ret = false; + ret = tls_record_is_start_marker(record) ? + MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL; goto out; } @@ -211,13 +220,13 @@ static bool tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx, while (remaining > 0) { skb_frag_t *frag = &record->frags[i]; - __skb_frag_ref(frag); + get_page(skb_frag_page(frag)); remaining -= skb_frag_size(frag); - info->frags[i++] = frag; + info->frags[i++] = *frag; } /* reduce the part which will be sent with the original SKB */ if (remaining < 0) - skb_frag_size_add(info->frags[i - 1], remaining); + skb_frag_size_add(&info->frags[i - 1], remaining); info->nr_frags = i; out: spin_unlock_irqrestore(&tx_ctx->lock, flags); @@ -229,17 +238,12 @@ tx_post_resync_params(struct mlx5e_txqsq *sq, struct mlx5e_ktls_offload_context_tx *priv_tx, u64 rcd_sn) { - struct tls_crypto_info *crypto_info = priv_tx->crypto_info; - struct tls12_crypto_info_aes_gcm_128 *info; + struct tls12_crypto_info_aes_gcm_128 *info = &priv_tx->crypto_info; __be64 rn_be = cpu_to_be64(rcd_sn); bool skip_static_post; u16 rec_seq_sz; char *rec_seq; - if (WARN_ON(crypto_info->cipher_type != TLS_CIPHER_AES_GCM_128)) - return; - - info = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info; rec_seq = info->rec_seq; rec_seq_sz = sizeof(info->rec_seq); @@ -250,11 +254,6 @@ tx_post_resync_params(struct mlx5e_txqsq *sq, mlx5e_ktls_tx_post_param_wqes(sq, priv_tx, skip_static_post, true); } -struct mlx5e_dump_wqe { - struct mlx5_wqe_ctrl_seg ctrl; - struct mlx5_wqe_data_seg data; -}; - static int tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool first) { @@ -262,7 +261,6 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool fir struct mlx5_wqe_data_seg *dseg; struct mlx5e_dump_wqe *wqe; dma_addr_t dma_addr = 0; - u8 num_wqebbs; u16 ds_cnt; int fsz; u16 pi; @@ -270,7 +268,6 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool fir wqe = mlx5e_sq_fetch_wqe(sq, sizeof(*wqe), &pi); ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS; - num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS); cseg = &wqe->ctrl; dseg = &wqe->data; @@ -291,24 +288,27 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool fir dseg->byte_count = cpu_to_be32(fsz); mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE); - tx_fill_wi(sq, pi, num_wqebbs, frag, fsz); - sq->pc += num_wqebbs; - - WARN(num_wqebbs > MLX5E_KTLS_MAX_DUMP_WQEBBS, - "unexpected DUMP num_wqebbs, %d > %d", - num_wqebbs, MLX5E_KTLS_MAX_DUMP_WQEBBS); + tx_fill_wi(sq, pi, MLX5E_KTLS_DUMP_WQEBBS, fsz, skb_frag_page(frag)); + sq->pc += MLX5E_KTLS_DUMP_WQEBBS; return 0; } void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq, struct mlx5e_tx_wqe_info *wi, - struct mlx5e_sq_dma *dma) + u32 *dma_fifo_cc) { - struct mlx5e_sq_stats *stats = sq->stats; + struct mlx5e_sq_stats *stats; + struct mlx5e_sq_dma *dma; + + if (!wi->resync_dump_frag_page) + return; + + dma = mlx5e_dma_get(sq, (*dma_fifo_cc)++); + stats = sq->stats; mlx5e_tx_dma_unmap(sq->pdev, dma); - __skb_frag_unref(wi->resync_dump_frag); + put_page(wi->resync_dump_frag_page); stats->tls_dump_packets++; stats->tls_dump_bytes += wi->num_bytes; } @@ -318,25 +318,31 @@ static void tx_post_fence_nop(struct mlx5e_txqsq *sq) struct mlx5_wq_cyc *wq = &sq->wq; u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); - tx_fill_wi(sq, pi, 1, NULL, 0); + tx_fill_wi(sq, pi, 1, 0, NULL); mlx5e_post_nop_fence(wq, sq->sqn, &sq->pc); } -static struct sk_buff * +static enum mlx5e_ktls_sync_retval mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, struct mlx5e_txqsq *sq, - struct sk_buff *skb, + int datalen, u32 seq) { struct mlx5e_sq_stats *stats = sq->stats; struct mlx5_wq_cyc *wq = &sq->wq; + enum mlx5e_ktls_sync_retval ret; struct tx_sync_info info = {}; u16 contig_wqebbs_room, pi; u8 num_wqebbs; - int i; - - if (!tx_sync_info_get(priv_tx, seq, &info)) { + int i = 0; + + ret = tx_sync_info_get(priv_tx, seq, &info); + if (unlikely(ret != MLX5E_KTLS_SYNC_DONE)) { + if (ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA) { + stats->tls_skip_no_sync_data++; + return MLX5E_KTLS_SYNC_SKIP_NO_DATA; + } /* We might get here if a retransmission reaches the driver * after the relevant record is acked. * It should be safe to drop the packet in this case @@ -346,13 +352,8 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, } if (unlikely(info.sync_len < 0)) { - u32 payload; - int headln; - - headln = skb_transport_offset(skb) + tcp_hdrlen(skb); - payload = skb->len - headln; - if (likely(payload <= -info.sync_len)) - return skb; + if (likely(datalen <= -info.sync_len)) + return MLX5E_KTLS_SYNC_DONE; stats->tls_drop_bypass_req++; goto err_out; @@ -360,30 +361,62 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx, stats->tls_ooo++; - num_wqebbs = MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS + - (info.nr_frags ? info.nr_frags * MLX5E_KTLS_MAX_DUMP_WQEBBS : 1); + tx_post_resync_params(sq, priv_tx, info.rcd_sn); + + /* If no dump WQE was sent, we need to have a fence NOP WQE before the + * actual data xmit. + */ + if (!info.nr_frags) { + tx_post_fence_nop(sq); + return MLX5E_KTLS_SYNC_DONE; + } + + num_wqebbs = mlx5e_ktls_dumps_num_wqebbs(sq, info.nr_frags, info.sync_len); pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi); + if (unlikely(contig_wqebbs_room < num_wqebbs)) mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room); tx_post_resync_params(sq, priv_tx, info.rcd_sn); - for (i = 0; i < info.nr_frags; i++) - if (tx_post_resync_dump(sq, info.frags[i], priv_tx->tisn, !i)) - goto err_out; + for (; i < info.nr_frags; i++) { + unsigned int orig_fsz, frag_offset = 0, n = 0; + skb_frag_t *f = &info.frags[i]; - /* If no dump WQE was sent, we need to have a fence NOP WQE before the - * actual data xmit. - */ - if (!info.nr_frags) - tx_post_fence_nop(sq); + orig_fsz = skb_frag_size(f); - return skb; + do { + bool fence = !(i || frag_offset); + unsigned int fsz; + + n++; + fsz = min_t(unsigned int, sq->hw_mtu, orig_fsz - frag_offset); + skb_frag_size_set(f, fsz); + if (tx_post_resync_dump(sq, f, priv_tx->tisn, fence)) { + page_ref_add(skb_frag_page(f), n - 1); + goto err_out; + } + + skb_frag_off_add(f, fsz); + frag_offset += fsz; + } while (frag_offset < orig_fsz); + + page_ref_add(skb_frag_page(f), n - 1); + } + + return MLX5E_KTLS_SYNC_DONE; err_out: - dev_kfree_skb_any(skb); - return NULL; + for (; i < info.nr_frags; i++) + /* The put_page() here undoes the page ref obtained in tx_sync_info_get(). + * Page refs obtained for the DUMP WQEs above (by page_ref_add) will be + * released only upon their completions (or in mlx5e_free_txqsq_descs, + * if channel closes). + */ + put_page(skb_frag_page(&info.frags[i])); + + return MLX5E_KTLS_SYNC_FAIL; } struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev, @@ -419,10 +452,15 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev, seq = ntohl(tcp_hdr(skb)->seq); if (unlikely(priv_tx->expected_seq != seq)) { - skb = mlx5e_ktls_tx_handle_ooo(priv_tx, sq, skb, seq); - if (unlikely(!skb)) + enum mlx5e_ktls_sync_retval ret = + mlx5e_ktls_tx_handle_ooo(priv_tx, sq, datalen, seq); + + if (likely(ret == MLX5E_KTLS_SYNC_DONE)) + *wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi); + else if (ret == MLX5E_KTLS_SYNC_FAIL) + goto err_out; + else /* ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA */ goto out; - *wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi); } priv_tx->expected_seq = seq + datalen; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index c5a9c20d7f006f554afea951f14da6b06ed8ca57..327c93a7bd55a843dfb16bf27ccdacf61e69efc0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1021,7 +1021,7 @@ static bool ext_link_mode_requested(const unsigned long *adver) { #define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ETHTOOL_LINK_MODE_50000baseKR_Full_BIT int size = __ETHTOOL_LINK_MODE_MASK_NBITS - MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT; - __ETHTOOL_DECLARE_LINK_MODE_MASK(modes); + __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = {0,}; bitmap_set(modes, MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT, size); return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 7569287f8f3c2129a92f6f2f0552051dd3762571..772bfdbdeb9c601f93354a654f02163c6db3fc17 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1128,6 +1128,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, sq->txq_ix = txq_ix; sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->min_inline_mode = params->tx_min_inline_mode; + sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); sq->stats = &c->priv->channel_stats[c->ix].sq[tc]; sq->stop_room = MLX5E_SQ_STOP_ROOM; INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work); @@ -1135,10 +1136,14 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, set_bit(MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, &sq->state); if (MLX5_IPSEC_DEV(c->priv->mdev)) set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state); +#ifdef CONFIG_MLX5_EN_TLS if (mlx5_accel_is_tls_device(c->priv->mdev)) { set_bit(MLX5E_SQ_STATE_TLS, &sq->state); - sq->stop_room += MLX5E_SQ_TLS_ROOM; + sq->stop_room += MLX5E_SQ_TLS_ROOM + + mlx5e_ktls_dumps_num_wqebbs(sq, MAX_SKB_FRAGS, + TLS_MAX_PAYLOAD_SIZE); } +#endif param->wq.db_numa_node = cpu_to_node(c->cpu); err = mlx5_wq_cyc_create(mdev, ¶m->wq, sqc_wq, wq, &sq->wq_ctrl); @@ -1349,9 +1354,13 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq) /* last doorbell out, godspeed .. */ if (mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1)) { u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); + struct mlx5e_tx_wqe_info *wi; struct mlx5e_tx_wqe *nop; - sq->db.wqe_info[pi].skb = NULL; + wi = &sq->db.wqe_info[pi]; + + memset(wi, 0, sizeof(*wi)); + wi->num_wqebbs = 1; nop = mlx5e_post_nop(wq, sq->sqn, &sq->pc); mlx5e_notify_hw(wq, sq->pc, sq->uar_map, &nop->ctrl); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 95892a3b63a13578e5532f63c96cadf0edaa434e..cd9bb7c7b3413651a9835925d69305299d007dcf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -611,8 +611,8 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv, mutex_lock(&esw->offloads.encap_tbl_lock); encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID); - if (e->compl_result || (encap_connected == neigh_connected && - ether_addr_equal(e->h_dest, ha))) + if (e->compl_result < 0 || (encap_connected == neigh_connected && + ether_addr_equal(e->h_dest, ha))) goto unlock; mlx5e_take_all_encap_flows(e, &flow_list); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index d6a547238de03fd9778d7f786346c00647963c68..82cffb3a99640f25fa6f6c0a8f52151194874058 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1386,8 +1386,11 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget) if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state))) return 0; - if (rq->cqd.left) + if (rq->cqd.left) { work_done += mlx5e_decompress_cqes_cont(rq, cqwq, 0, budget); + if (rq->cqd.left || work_done >= budget) + goto out; + } cqe = mlx5_cqwq_get_cqe(cqwq); if (!cqe) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c index 840ec945ccbab466863fb6f43a29bbfd23d08c4a..bbff8d8ded767ce411dca360fe43ef5a3942ef26 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c @@ -35,6 +35,7 @@ #include #include #include "en.h" +#include "en/port.h" enum { MLX5E_ST_LINK_STATE, @@ -80,22 +81,12 @@ static int mlx5e_test_link_state(struct mlx5e_priv *priv) static int mlx5e_test_link_speed(struct mlx5e_priv *priv) { - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; - u32 eth_proto_oper; - int i; + u32 speed; if (!netif_carrier_ok(priv->netdev)) return 1; - if (mlx5_query_port_ptys(priv->mdev, out, sizeof(out), MLX5_PTYS_EN, 1)) - return 1; - - eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); - for (i = 0; i < MLX5E_LINK_MODES_NUMBER; i++) { - if (eth_proto_oper & MLX5E_PROT_MASK(i)) - return 0; - } - return 1; + return mlx5e_port_linkspeed(priv->mdev, &speed); } struct mlx5ehdr { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index ac6fdcda7019b28c92c11bc1257705e23698e988..7e6ebd0505cc044963493e58563f45661b652441 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -52,11 +52,12 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_bytes) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ctx) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_packets) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_bytes) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_resync_bytes) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_skip_no_sync_data) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_no_sync_data) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_bypass_req) }, - { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_packets) }, - { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_bytes) }, #endif { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_lro_packets) }, @@ -288,11 +289,12 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv) s->tx_tls_encrypted_bytes += sq_stats->tls_encrypted_bytes; s->tx_tls_ctx += sq_stats->tls_ctx; s->tx_tls_ooo += sq_stats->tls_ooo; + s->tx_tls_dump_bytes += sq_stats->tls_dump_bytes; + s->tx_tls_dump_packets += sq_stats->tls_dump_packets; s->tx_tls_resync_bytes += sq_stats->tls_resync_bytes; + s->tx_tls_skip_no_sync_data += sq_stats->tls_skip_no_sync_data; s->tx_tls_drop_no_sync_data += sq_stats->tls_drop_no_sync_data; s->tx_tls_drop_bypass_req += sq_stats->tls_drop_bypass_req; - s->tx_tls_dump_bytes += sq_stats->tls_dump_bytes; - s->tx_tls_dump_packets += sq_stats->tls_dump_packets; #endif s->tx_cqes += sq_stats->cqes; } @@ -1472,10 +1474,12 @@ static const struct counter_desc sq_stats_desc[] = { { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_bytes) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ctx) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ooo) }, - { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_no_sync_data) }, - { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_bypass_req) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_packets) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_bytes) }, + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_resync_bytes) }, + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_skip_no_sync_data) }, + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_no_sync_data) }, + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_bypass_req) }, #endif { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_none) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, stopped) }, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 79f261bf86ac8e54932b7a0ef2c925fd2fd54d3c..869f3502f6312845e35d888f972a5a78a8a3b84e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -129,11 +129,12 @@ struct mlx5e_sw_stats { u64 tx_tls_encrypted_bytes; u64 tx_tls_ctx; u64 tx_tls_ooo; + u64 tx_tls_dump_packets; + u64 tx_tls_dump_bytes; u64 tx_tls_resync_bytes; + u64 tx_tls_skip_no_sync_data; u64 tx_tls_drop_no_sync_data; u64 tx_tls_drop_bypass_req; - u64 tx_tls_dump_packets; - u64 tx_tls_dump_bytes; #endif u64 rx_xsk_packets; @@ -273,11 +274,12 @@ struct mlx5e_sq_stats { u64 tls_encrypted_bytes; u64 tls_ctx; u64 tls_ooo; + u64 tls_dump_packets; + u64 tls_dump_bytes; u64 tls_resync_bytes; + u64 tls_skip_no_sync_data; u64 tls_drop_no_sync_data; u64 tls_drop_bypass_req; - u64 tls_dump_packets; - u64 tls_dump_bytes; #endif /* less likely accessed in data path */ u64 csum_none; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 3e78a727f3e68634e2fb5f7e65838dce963a90bc..fda0b37075e8c444bdf2adba3a0e5dc47ca47adf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1278,8 +1278,10 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, mlx5_eswitch_del_vlan_action(esw, attr); for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) - if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) + if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) { mlx5e_detach_encap(priv, flow, out_index); + kfree(attr->parse_attr->tun_info[out_index]); + } kvfree(attr->parse_attr); if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) @@ -1559,6 +1561,7 @@ static void mlx5e_encap_dealloc(struct mlx5e_priv *priv, struct mlx5e_encap_entr mlx5_packet_reformat_dealloc(priv->mdev, e->pkt_reformat); } + kfree(e->tun_info); kfree(e->encap_header); kfree_rcu(e, rcu); } @@ -2972,6 +2975,13 @@ mlx5e_encap_get(struct mlx5e_priv *priv, struct encap_key *key, return NULL; } +static struct ip_tunnel_info *dup_tun_info(const struct ip_tunnel_info *tun_info) +{ + size_t tun_size = sizeof(*tun_info) + tun_info->options_len; + + return kmemdup(tun_info, tun_size, GFP_KERNEL); +} + static int mlx5e_attach_encap(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, struct net_device *mirred_dev, @@ -3028,13 +3038,15 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, refcount_set(&e->refcnt, 1); init_completion(&e->res_ready); + tun_info = dup_tun_info(tun_info); + if (!tun_info) { + err = -ENOMEM; + goto out_err_init; + } e->tun_info = tun_info; err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack); - if (err) { - kfree(e); - e = NULL; - goto out_err; - } + if (err) + goto out_err_init; INIT_LIST_HEAD(&e->flows); hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); @@ -3075,6 +3087,12 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, if (e) mlx5e_encap_put(priv, e); return err; + +out_err_init: + mutex_unlock(&esw->offloads.encap_tbl_lock); + kfree(tun_info); + kfree(e); + return err; } static int parse_tc_vlan_action(struct mlx5e_priv *priv, @@ -3160,7 +3178,7 @@ static int add_vlan_pop_action(struct mlx5e_priv *priv, struct mlx5_esw_flow_attr *attr, u32 *action) { - int nest_level = vlan_get_encap_level(attr->parse_attr->filter_dev); + int nest_level = attr->parse_attr->filter_dev->lower_level; struct flow_action_entry vlan_act = { .id = FLOW_ACTION_VLAN_POP, }; @@ -3295,7 +3313,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, } else if (encap) { parse_attr->mirred_ifindex[attr->out_count] = out_dev->ifindex; - parse_attr->tun_info[attr->out_count] = info; + parse_attr->tun_info[attr->out_count] = dup_tun_info(info); + if (!parse_attr->tun_info[attr->out_count]) + return -ENOMEM; encap = false; attr->dests[attr->out_count].flags |= MLX5_ESW_DEST_ENCAP; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index d3a67a9b4eba76076ea899a82649f027e0603a92..67dc4f0921b649f7f38c750c4069d042261d1777 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -403,7 +403,10 @@ netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev) static void mlx5e_dump_error_cqe(struct mlx5e_txqsq *sq, struct mlx5_err_cqe *err_cqe) { - u32 ci = mlx5_cqwq_get_ci(&sq->cq.wq); + struct mlx5_cqwq *wq = &sq->cq.wq; + u32 ci; + + ci = mlx5_cqwq_ctr2ix(wq, wq->cc - 1); netdev_err(sq->channel->netdev, "Error cqe on cqn 0x%x, ci 0x%x, sqn 0x%x, opcode 0x%x, syndrome 0x%x, vendor syndrome 0x%x\n", @@ -479,14 +482,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) skb = wi->skb; if (unlikely(!skb)) { -#ifdef CONFIG_MLX5_EN_TLS - if (wi->resync_dump_frag) { - struct mlx5e_sq_dma *dma = - mlx5e_dma_get(sq, dma_fifo_cc++); - - mlx5e_ktls_tx_handle_resync_dump_comp(sq, wi, dma); - } -#endif + mlx5e_ktls_tx_handle_resync_dump_comp(sq, wi, &dma_fifo_cc); sqcc += wi->num_wqebbs; continue; } @@ -542,29 +538,38 @@ void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq) { struct mlx5e_tx_wqe_info *wi; struct sk_buff *skb; + u32 dma_fifo_cc; + u16 sqcc; u16 ci; int i; - while (sq->cc != sq->pc) { - ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sq->cc); + sqcc = sq->cc; + dma_fifo_cc = sq->dma_fifo_cc; + + while (sqcc != sq->pc) { + ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc); wi = &sq->db.wqe_info[ci]; skb = wi->skb; - if (!skb) { /* nop */ - sq->cc++; + if (!skb) { + mlx5e_ktls_tx_handle_resync_dump_comp(sq, wi, &dma_fifo_cc); + sqcc += wi->num_wqebbs; continue; } for (i = 0; i < wi->num_dma; i++) { struct mlx5e_sq_dma *dma = - mlx5e_dma_get(sq, sq->dma_fifo_cc++); + mlx5e_dma_get(sq, dma_fifo_cc++); mlx5e_tx_dma_unmap(sq->pdev, dma); } dev_kfree_skb_any(skb); - sq->cc += wi->num_wqebbs; + sqcc += wi->num_wqebbs; } + + sq->dma_fifo_cc = dma_fifo_cc; + sq->cc = sqcc; } #ifdef CONFIG_MLX5_CORE_IPOIB diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 00d71db15f2217f437b4d8438d1a8087d35ab080..369499e88fe8d1382a1db5322bdcff11a599934e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -285,7 +285,6 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw, mlx5_eswitch_set_rule_source_port(esw, spec, attr); - spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS; if (attr->outer_match_level != MLX5_MATCH_NONE) spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c index 1d55a324a17e3d00b779d8fce3ad77b914471bdb..7879e1746297c0cb533a202193775db174f22b99 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c @@ -177,22 +177,32 @@ mlx5_eswitch_termtbl_actions_move(struct mlx5_flow_act *src, memset(&src->vlan[1], 0, sizeof(src->vlan[1])); } +static bool mlx5_eswitch_offload_is_uplink_port(const struct mlx5_eswitch *esw, + const struct mlx5_flow_spec *spec) +{ + u32 port_mask, port_value; + + if (MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source)) + return spec->flow_context.flow_source == MLX5_VPORT_UPLINK; + + port_mask = MLX5_GET(fte_match_param, spec->match_criteria, + misc_parameters.source_port); + port_value = MLX5_GET(fte_match_param, spec->match_value, + misc_parameters.source_port); + return (port_mask & port_value & 0xffff) == MLX5_VPORT_UPLINK; +} + bool mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw, struct mlx5_flow_act *flow_act, struct mlx5_flow_spec *spec) { - u32 port_mask = MLX5_GET(fte_match_param, spec->match_criteria, - misc_parameters.source_port); - u32 port_value = MLX5_GET(fte_match_param, spec->match_value, - misc_parameters.source_port); - if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, termination_table)) return false; /* push vlan on RX */ return (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) && - ((port_mask & port_value) == MLX5_VPORT_UPLINK); + mlx5_eswitch_offload_is_uplink_port(esw, spec); } struct mlx5_flow_handle * diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c index 4c50efe4e7f11878895a98db4305b52d21bcbb15..61021133029e6a62452bbbad84d7894ef6df00bd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c @@ -464,8 +464,10 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size) } err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn, &irqn); - if (err) + if (err) { + kvfree(in); goto err_cqwq; + } cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context); MLX5_SET(cqc, cqc, log_cq_size, ilog2(cq_size)); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 579c306caa7b10345c5a0f9ae7c9892d489f1de9..3c816e81f8d9bab405cbeeb3901d40341cbdd60d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -507,7 +507,8 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, MLX5_SET(dest_format_struct, in_dests, destination_eswitch_owner_vhca_id, dst->dest_attr.vport.vhca_id); - if (extended_dest) { + if (extended_dest && + dst->dest_attr.vport.pkt_reformat) { MLX5_SET(dest_format_struct, in_dests, packet_reformat, !!(dst->dest_attr.vport.flags & diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index d685122d9ff761794a7f89d860a90e25801f29fc..c07f3154437c6062679fd241522eb91f4afed771 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -572,7 +572,7 @@ mlx5_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter, return -ENOMEM; err = mlx5_crdump_collect(dev, cr_data); if (err) - return err; + goto free_data; if (priv_ctx) { struct mlx5_fw_reporter_ctx *fw_reporter_ctx = priv_ctx; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c index 4187f2b112b8e2e81f38d50a2daadc1ea666bd4c..e8b656075c6ff3d90a3d857fbb4bbab752183c33 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c @@ -788,12 +788,10 @@ dr_rule_handle_ste_branch(struct mlx5dr_rule *rule, * it means that all the previous stes are the same, * if so, this rule is duplicated. */ - if (mlx5dr_ste_is_last_in_rule(nic_matcher, - matched_ste->ste_chain_location)) { - mlx5dr_info(dmn, "Duplicate rule inserted, aborting!!\n"); - return NULL; - } - return matched_ste; + if (!mlx5dr_ste_is_last_in_rule(nic_matcher, ste_location)) + return matched_ste; + + mlx5dr_dbg(dmn, "Duplicate rule inserted\n"); } if (!skip_rehash && dr_rule_need_enlarge_hash(cur_htbl, dmn, nic_dmn)) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 14dcc786926ddc22ea93c6820cc117df40dd6316..4421ab22182fe7c5d254dba03e5b3ab415ea392a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1186,7 +1186,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, if (err) goto err_thermal_init; - if (mlxsw_driver->params_register && !reload) + if (mlxsw_driver->params_register) devlink_params_publish(devlink); return 0; @@ -1259,7 +1259,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, return; } - if (mlxsw_core->driver->params_unregister && !reload) + if (mlxsw_core->driver->params_unregister) devlink_params_unpublish(devlink); mlxsw_thermal_fini(mlxsw_core->thermal); mlxsw_hwmon_fini(mlxsw_core->hwmon); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c index 899450b28621e59bc4f5c1c1c0aa8f972852788b..7c03b661ae7ea218fe562afc14e7448d76c99104 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c @@ -99,6 +99,7 @@ static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port, devlink = priv_to_devlink(mlxsw_sp->core); in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core, local_port); + skb_push(skb, ETH_HLEN); devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port); consume_skb(skb); } diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 4d1bce4389c792a163b87938e4b8142a83808c2e..344539c0d3aac90f27c5ea9672b2a6878b0ab320 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -261,8 +261,15 @@ static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid, port->pvid = vid; /* Untagged egress vlan clasification */ - if (untagged) + if (untagged && port->vid != vid) { + if (port->vid) { + dev_err(ocelot->dev, + "Port already has a native VLAN: %d\n", + port->vid); + return -EBUSY; + } port->vid = vid; + } ocelot_vlan_port_apply(ocelot, port); @@ -934,7 +941,7 @@ static int ocelot_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, static int ocelot_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) { - return ocelot_vlan_vid_add(dev, vid, false, true); + return ocelot_vlan_vid_add(dev, vid, false, false); } static int ocelot_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c index 1eef446036d6a2be6bd4acb306c782f7b169f2f1..79d72c88bbef2a16a584bef5359e958fc001344d 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c @@ -299,22 +299,6 @@ static void nfp_repr_clean(struct nfp_repr *repr) nfp_port_free(repr->port); } -static struct lock_class_key nfp_repr_netdev_xmit_lock_key; -static struct lock_class_key nfp_repr_netdev_addr_lock_key; - -static void nfp_repr_set_lockdep_class_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, &nfp_repr_netdev_xmit_lock_key); -} - -static void nfp_repr_set_lockdep_class(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, &nfp_repr_netdev_addr_lock_key); - netdev_for_each_tx_queue(dev, nfp_repr_set_lockdep_class_one, NULL); -} - int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, u32 cmsg_port_id, struct nfp_port *port, struct net_device *pf_netdev) @@ -324,8 +308,6 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, u32 repr_cap = nn->tlv_caps.repr_cap; int err; - nfp_repr_set_lockdep_class(netdev); - repr->port = port; repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL); if (!repr->dst) diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 141571e2ec11152797a9267c77a5f13e3b7887d3..544012a67221ac04a915441146cc2baf2b8c55a5 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1356,9 +1356,6 @@ static int lpc_eth_drv_probe(struct platform_device *pdev) if (!is_valid_ether_addr(ndev->dev_addr)) eth_hw_addr_random(ndev); - /* Reset the ethernet controller */ - __lpc_eth_reset(pldat); - /* then shut everything down to save power */ __lpc_eth_shutdown(pldat); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 72107a0627a9957de0ce4c01e6b561f37599b510..20faa8d24c9ffea255d25bf5103b16f94613d301 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ +#include +#include #include #include #include diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index 812190e729c2d95f0cd9c54ecc319eac0308ebb9..6a95b42a8d8c4037ad4b85d8715e13946b2db6a3 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -182,6 +182,8 @@ struct ionic_lif { #define lif_to_txqcq(lif, i) ((lif)->txqcqs[i].qcq) #define lif_to_rxqcq(lif, i) ((lif)->rxqcqs[i].qcq) +#define lif_to_txstats(lif, i) ((lif)->txqcqs[i].stats->tx) +#define lif_to_rxstats(lif, i) ((lif)->rxqcqs[i].stats->rx) #define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q) #define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index 15e432386b35a2ad0733c0df28e4002588bb66ea..aab3114134128f578fc2eb4acf849bcabe282df2 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ +#include +#include #include #include #include diff --git a/drivers/net/ethernet/pensando/ionic/ionic_stats.c b/drivers/net/ethernet/pensando/ionic/ionic_stats.c index e2907884f843fd7ae7e982cfbdf595dc5c4b4856..03916b6d47f2236308415b925f7e3d7f280562b4 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_stats.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_stats.c @@ -117,7 +117,8 @@ static u64 ionic_sw_stats_get_count(struct ionic_lif *lif) /* rx stats */ total += MAX_Q(lif) * IONIC_NUM_RX_STATS; - if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { + if (test_bit(IONIC_LIF_UP, lif->state) && + test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { /* tx debug stats */ total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS + IONIC_NUM_TX_Q_STATS + @@ -149,7 +150,8 @@ static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf) *buf += ETH_GSTRING_LEN; } - if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { + if (test_bit(IONIC_LIF_UP, lif->state) && + test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) { snprintf(*buf, ETH_GSTRING_LEN, "txq_%d_%s", @@ -187,7 +189,8 @@ static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf) *buf += ETH_GSTRING_LEN; } - if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { + if (test_bit(IONIC_LIF_UP, lif->state) && + test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { snprintf(*buf, ETH_GSTRING_LEN, "rxq_%d_cq_%s", @@ -223,6 +226,8 @@ static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) { struct ionic_lif_sw_stats lif_stats; struct ionic_qcq *txqcq, *rxqcq; + struct ionic_tx_stats *txstats; + struct ionic_rx_stats *rxstats; int i, q_num; ionic_get_lif_stats(lif, &lif_stats); @@ -233,15 +238,17 @@ static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) } for (q_num = 0; q_num < MAX_Q(lif); q_num++) { - txqcq = lif_to_txqcq(lif, q_num); + txstats = &lif_to_txstats(lif, q_num); for (i = 0; i < IONIC_NUM_TX_STATS; i++) { - **buf = IONIC_READ_STAT64(&txqcq->stats->tx, + **buf = IONIC_READ_STAT64(txstats, &ionic_tx_stats_desc[i]); (*buf)++; } - if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { + if (test_bit(IONIC_LIF_UP, lif->state) && + test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { + txqcq = lif_to_txqcq(lif, q_num); for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) { **buf = IONIC_READ_STAT64(&txqcq->q, &ionic_txq_stats_desc[i]); @@ -258,22 +265,24 @@ static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) (*buf)++; } for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { - **buf = txqcq->stats->tx.sg_cntr[i]; + **buf = txstats->sg_cntr[i]; (*buf)++; } } } for (q_num = 0; q_num < MAX_Q(lif); q_num++) { - rxqcq = lif_to_rxqcq(lif, q_num); + rxstats = &lif_to_rxstats(lif, q_num); for (i = 0; i < IONIC_NUM_RX_STATS; i++) { - **buf = IONIC_READ_STAT64(&rxqcq->stats->rx, + **buf = IONIC_READ_STAT64(rxstats, &ionic_rx_stats_desc[i]); (*buf)++; } - if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { + if (test_bit(IONIC_LIF_UP, lif->state) && + test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { + rxqcq = lif_to_rxqcq(lif, q_num); for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { **buf = IONIC_READ_STAT64(&rxqcq->cq, &ionic_dbg_cq_stats_desc[i]); diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 2ce70097d018b8e7e846e71d4a9b79204838c0cf..38f7f40b3a4d0dd5773a24185e6602d7479fc8b7 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -67,10 +67,9 @@ #define QED_ROCE_QPS (8192) #define QED_ROCE_DPIS (8) #define QED_RDMA_SRQS QED_ROCE_QPS -#define QED_NVM_CFG_SET_FLAGS 0xE -#define QED_NVM_CFG_SET_PF_FLAGS 0x1E #define QED_NVM_CFG_GET_FLAGS 0xA #define QED_NVM_CFG_GET_PF_FLAGS 0x1A +#define QED_NVM_CFG_MAX_ATTRS 50 static char version[] = "QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n"; @@ -2255,6 +2254,7 @@ static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data) { struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); u8 entity_id, len, buf[32]; + bool need_nvm_init = true; struct qed_ptt *ptt; u16 cfg_id, count; int rc = 0, i; @@ -2271,8 +2271,10 @@ static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data) DP_VERBOSE(cdev, NETIF_MSG_DRV, "Read config ids: num_attrs = %0d\n", count); - /* NVM CFG ID attributes */ - for (i = 0; i < count; i++) { + /* NVM CFG ID attributes. Start loop index from 1 to avoid additional + * arithmetic operations in the implementation. + */ + for (i = 1; i <= count; i++) { cfg_id = *((u16 *)*data); *data += 2; entity_id = **data; @@ -2282,8 +2284,21 @@ static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data) memcpy(buf, *data, len); *data += len; - flags = entity_id ? QED_NVM_CFG_SET_PF_FLAGS : - QED_NVM_CFG_SET_FLAGS; + flags = 0; + if (need_nvm_init) { + flags |= QED_NVM_CFG_OPTION_INIT; + need_nvm_init = false; + } + + /* Commit to flash and free the resources */ + if (!(i % QED_NVM_CFG_MAX_ATTRS) || i == count) { + flags |= QED_NVM_CFG_OPTION_COMMIT | + QED_NVM_CFG_OPTION_FREE; + need_nvm_init = true; + } + + if (entity_id) + flags |= QED_NVM_CFG_OPTION_ENTITY_SEL; DP_VERBOSE(cdev, NETIF_MSG_DRV, "cfg_id = %d entity = %d len = %d\n", cfg_id, diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index 78f77b712b1012509528e3a9f2889d6ea057b596..dcb5c917f3733fd60642bbff0dc45104bd91902c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -2005,7 +2005,7 @@ static void qed_iov_vf_mbx_stop_vport(struct qed_hwfn *p_hwfn, (qed_iov_validate_active_txq(p_hwfn, vf))) { vf->b_malicious = true; DP_NOTICE(p_hwfn, - "VF [%02x] - considered malicious; Unable to stop RX/TX queuess\n", + "VF [%02x] - considered malicious; Unable to stop RX/TX queues\n", vf->abs_vf_id); status = PFVF_STATUS_MALICIOUS; goto out; diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 74f81fe03810c419279a7b200190fdbbd3c99ed6..5064c292b873d294481e678782bc4949c709e3c6 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -1029,6 +1029,10 @@ static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg) { int value; + /* Work around issue with chip reporting wrong PHY ID */ + if (reg == MII_PHYSID2) + return 0xc912; + r8168dp_2_mdio_start(tp); value = r8169_mdio_read(tp, reg); @@ -4146,6 +4150,14 @@ static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) rtl_lock_config_regs(tp); } +static void rtl_jumbo_config(struct rtl8169_private *tp, int mtu) +{ + if (mtu > ETH_DATA_LEN) + rtl_hw_jumbo_enable(tp); + else + rtl_hw_jumbo_disable(tp); +} + DECLARE_RTL_COND(rtl_chipcmd_cond) { return RTL_R8(tp, ChipCmd) & CmdReset; @@ -4442,11 +4454,6 @@ static void rtl8168g_set_pause_thresholds(struct rtl8169_private *tp, static void rtl_hw_start_8168bb(struct rtl8169_private *tp) { RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (tp->dev->mtu <= ETH_DATA_LEN) { - rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B | - PCI_EXP_DEVCTL_NOSNOOP_EN); - } } static void rtl_hw_start_8168bef(struct rtl8169_private *tp) @@ -4462,9 +4469,6 @@ static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B); - rtl_disable_clock_request(tp); } @@ -4490,9 +4494,6 @@ static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp) rtl_set_def_aspm_entry_latency(tp); RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B); } static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp) @@ -4503,9 +4504,6 @@ static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp) /* Magic. */ RTL_W8(tp, DBG_REG, 0x20); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B); } static void rtl_hw_start_8168c_1(struct rtl8169_private *tp) @@ -4611,9 +4609,6 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) rtl_ephy_init(tp, e_info_8168e_1); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B); - rtl_disable_clock_request(tp); /* Reset tx FIFO pointer */ @@ -4636,9 +4631,6 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) rtl_ephy_init(tp, e_info_8168e_2); - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B); - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000); rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000); rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06); @@ -5485,6 +5477,8 @@ static void rtl_hw_start(struct rtl8169_private *tp) rtl_set_rx_tx_desc_registers(tp); rtl_lock_config_regs(tp); + rtl_jumbo_config(tp, tp->dev->mtu); + /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ RTL_R16(tp, CPlusCmd); RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); @@ -5498,10 +5492,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) { struct rtl8169_private *tp = netdev_priv(dev); - if (new_mtu > ETH_DATA_LEN) - rtl_hw_jumbo_enable(tp); - else - rtl_hw_jumbo_disable(tp); + rtl_jumbo_config(tp, new_mtu); dev->mtu = new_mtu; netdev_update_features(dev); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index f97a4096f8fc8e44ef2456e822952a885e48de83..ddcc191febdb22db310fe9833bb39facfbc1de74 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -651,7 +651,8 @@ static void sun8i_dwmac_set_filter(struct mac_device_info *hw, } } } else { - netdev_info(dev, "Too many address, switching to promiscuous\n"); + if (!(readl(ioaddr + EMAC_RX_FRM_FLT) & EMAC_FRM_FLT_RXALL)) + netdev_info(dev, "Too many address, switching to promiscuous\n"); v = EMAC_FRM_FLT_RXALL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 2cb9c53f93b84171d5a948dcb9f6218dacb5ae16..5a7b0aca1d31af097ece2070ad0f657be3ea49bf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -448,7 +448,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw, value |= GMAC_PACKET_FILTER_HPF; /* Handle multiple unicast addresses */ - if (netdev_uc_count(dev) > GMAC_MAX_PERFECT_ADDRESSES) { + if (netdev_uc_count(dev) > hw->unicast_filter_entries) { /* Switch to promiscuous mode if more than 128 addrs * are required */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c index 3f4f3132e16b3b019869de9c6a219eb677e628a4..e436fa160c7d6a473f46f68c0facc1a31b0dc69a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c @@ -515,6 +515,7 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index, if (!enable) { val |= PPSCMDx(index, 0x5); + val |= PPSEN0; writel(val, ioaddr + MAC_PPS_CONTROL); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c76a1336a4517f50c3d7c48736c98f3b06f92371..4e9c848c67ccc93477839c34959cb6f3760e7e35 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2610,7 +2610,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) } if (priv->hw->pcs) - stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0); + stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, priv->hw->ps, 0); /* set TX and RX rings length */ stmmac_set_rings_length(priv); @@ -2995,6 +2995,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) } else { stmmac_set_desc_addr(priv, first, des); tmp_pay_len = pay_len; + des += proto_hdr_len; } stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue); @@ -4742,8 +4743,10 @@ int stmmac_suspend(struct device *dev) stmmac_mac_set(priv, priv->ioaddr, false); pinctrl_pm_select_sleep_state(priv->device); /* Disable clock in case of PWM is off */ - clk_disable(priv->plat->pclk); - clk_disable(priv->plat->stmmac_clk); + if (priv->plat->clk_ptp_ref) + clk_disable_unprepare(priv->plat->clk_ptp_ref); + clk_disable_unprepare(priv->plat->pclk); + clk_disable_unprepare(priv->plat->stmmac_clk); } mutex_unlock(&priv->lock); @@ -4806,8 +4809,10 @@ int stmmac_resume(struct device *dev) } else { pinctrl_pm_select_default_state(priv->device); /* enable the clk previously disabled */ - clk_enable(priv->plat->stmmac_clk); - clk_enable(priv->plat->pclk); + clk_prepare_enable(priv->plat->stmmac_clk); + clk_prepare_enable(priv->plat->pclk); + if (priv->plat->clk_ptp_ref) + clk_prepare_enable(priv->plat->clk_ptp_ref); /* reset the phy so that it's ready */ if (priv->mii) stmmac_mdio_reset(priv->mii); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c index 173493db038c0a9f5199bf1675429e0b379a6b4f..df638b18b72c7f895c6cb65b13b5119902fc30b8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c @@ -164,7 +164,7 @@ static int stmmac_enable(struct ptp_clock_info *ptp, /* structure describing a PTP hardware clock */ static struct ptp_clock_info stmmac_ptp_clock_ops = { .owner = THIS_MODULE, - .name = "stmmac_ptp_clock", + .name = "stmmac ptp", .max_adj = 62500000, .n_alarm = 0, .n_ext_ts = 0, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index cc76a42c7466c27cc7d025bc94a03014d6bcfda3..e4ac3c4014328c50402f10bdf59c96a05e86f351 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -487,8 +487,8 @@ static int stmmac_filter_check(struct stmmac_priv *priv) static int stmmac_test_hfilt(struct stmmac_priv *priv) { - unsigned char gd_addr[ETH_ALEN] = {0x01, 0x00, 0xcc, 0xcc, 0xdd, 0xdd}; - unsigned char bd_addr[ETH_ALEN] = {0x09, 0x00, 0xaa, 0xaa, 0xbb, 0xbb}; + unsigned char gd_addr[ETH_ALEN] = {0x01, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}; + unsigned char bd_addr[ETH_ALEN] = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05}; struct stmmac_packet_attrs attr = { }; int ret; @@ -496,6 +496,9 @@ static int stmmac_test_hfilt(struct stmmac_priv *priv) if (ret) return ret; + if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins) + return -EOPNOTSUPP; + ret = dev_mc_add(priv->dev, gd_addr); if (ret) return ret; @@ -573,6 +576,8 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv) if (stmmac_filter_check(priv)) return -EOPNOTSUPP; + if (!priv->hw->multicast_filter_bins) + return -EOPNOTSUPP; /* Remove all MC addresses */ __dev_mc_unsync(priv->dev, NULL); @@ -611,6 +616,8 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv) if (stmmac_filter_check(priv)) return -EOPNOTSUPP; + if (!priv->hw->multicast_filter_bins) + return -EOPNOTSUPP; /* Remove all UC addresses */ __dev_uc_unsync(priv->dev, NULL); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index e231098061b6e842574002c5edd2f48d96e6e71c..f9a9a9d82233375638dacb3c1b3048d11c6efb30 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -510,7 +510,7 @@ static struct stmmac_flow_entry *tc_find_flow(struct stmmac_priv *priv, return NULL; } -struct { +static struct { int (*fn)(struct stmmac_priv *priv, struct flow_cls_offload *cls, struct stmmac_flow_entry *entry); } tc_flow_parsers[] = { diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index a65edd2770e66e23bf5faedc9912c64555f3ec52..37ba708ac78136c70df9897999fd8c2c28e96302 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -722,7 +722,7 @@ static void cpdma_chan_set_descs(struct cpdma_ctlr *ctlr, * cpdma_chan_split_pool - Splits ctrl pool between all channels. * Has to be called under ctlr lock */ -int cpdma_chan_split_pool(struct cpdma_ctlr *ctlr) +static int cpdma_chan_split_pool(struct cpdma_ctlr *ctlr) { int tx_per_ch_desc = 0, rx_per_ch_desc = 0; int free_rx_num = 0, free_tx_num = 0; diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index bbbc1dcb6ab5ca169cca257dcabf8705e08b5af0..b517c1af9de052d6d5fcc2d8b249d8544d5b49b9 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -1237,8 +1237,17 @@ static int fjes_probe(struct platform_device *plat_dev) adapter->open_guard = false; adapter->txrx_wq = alloc_workqueue(DRV_NAME "/txrx", WQ_MEM_RECLAIM, 0); + if (unlikely(!adapter->txrx_wq)) { + err = -ENOMEM; + goto err_free_netdev; + } + adapter->control_wq = alloc_workqueue(DRV_NAME "/control", WQ_MEM_RECLAIM, 0); + if (unlikely(!adapter->control_wq)) { + err = -ENOMEM; + goto err_free_txrx_wq; + } INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task); INIT_WORK(&adapter->raise_intr_rxdata_task, @@ -1255,7 +1264,7 @@ static int fjes_probe(struct platform_device *plat_dev) hw->hw_res.irq = platform_get_irq(plat_dev, 0); err = fjes_hw_init(&adapter->hw); if (err) - goto err_free_netdev; + goto err_free_control_wq; /* setup MAC address (02:00:00:00:00:[epid])*/ netdev->dev_addr[0] = 2; @@ -1277,6 +1286,10 @@ static int fjes_probe(struct platform_device *plat_dev) err_hw_exit: fjes_hw_exit(&adapter->hw); +err_free_control_wq: + destroy_workqueue(adapter->control_wq); +err_free_txrx_wq: + destroy_workqueue(adapter->txrx_wq); err_free_netdev: free_netdev(netdev); err_out: diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index fbec711ff514af3da11fa9473fe2ef0c1732ba5c..fbea6f232819e905f0fedd832127f4f9ab7a4aba 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -107,27 +107,6 @@ struct bpqdev { static LIST_HEAD(bpq_devices); -/* - * bpqether network devices are paired with ethernet devices below them, so - * form a special "super class" of normal ethernet devices; split their locks - * off into a separate class since they always nest. - */ -static struct lock_class_key bpq_netdev_xmit_lock_key; -static struct lock_class_key bpq_netdev_addr_lock_key; - -static void bpq_set_lockdep_class_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, &bpq_netdev_xmit_lock_key); -} - -static void bpq_set_lockdep_class(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, &bpq_netdev_addr_lock_key); - netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL); -} - /* ------------------------------------------------------------------------ */ @@ -498,7 +477,6 @@ static int bpq_new_device(struct net_device *edev) err = register_netdevice(ndev); if (err) goto error; - bpq_set_lockdep_class(ndev); /* List protected by RTNL */ list_add_rcu(&bpq->bpq_list, &bpq_devices); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 39dddcd8b3cb0129d25c98400cca6692fa8b790c..963509add611ffc1de2f2ebbbfe13f9f58cb5d08 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -982,7 +982,7 @@ static int netvsc_attach(struct net_device *ndev, if (netif_running(ndev)) { ret = rndis_filter_open(nvdev); if (ret) - return ret; + goto err; rdev = nvdev->extension; if (!rdev->link_state) @@ -990,6 +990,13 @@ static int netvsc_attach(struct net_device *ndev, } return 0; + +err: + netif_device_detach(ndev); + + rndis_filter_device_remove(hdev, nvdev); + + return ret; } static int netvsc_set_channels(struct net_device *net, @@ -1807,8 +1814,10 @@ static int netvsc_set_features(struct net_device *ndev, ret = rndis_filter_set_offload_params(ndev, nvdev, &offloads); - if (ret) + if (ret) { features ^= NETIF_F_LRO; + ndev->features = features; + } syncvf: if (!vf_netdev) @@ -2335,8 +2344,6 @@ static int netvsc_probe(struct hv_device *dev, NETIF_F_HW_VLAN_CTAG_RX; net->vlan_features = net->features; - netdev_lockdep_set_classes(net); - /* MTU range: 68 - 1500 or 65521 */ net->min_mtu = NETVSC_MTU_MIN; if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 887bbba4631e7ffecd2d5158b0cc91644ba7ad8c..ba3dfac1d90433fc20650ba644990f7a339d3949 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -131,8 +131,6 @@ static int ipvlan_init(struct net_device *dev) dev->gso_max_segs = phy_dev->gso_max_segs; dev->hard_header_len = phy_dev->hard_header_len; - netdev_lockdep_set_classes(dev); - ipvlan->pcpu_stats = netdev_alloc_pcpu_stats(struct ipvl_pcpu_stats); if (!ipvlan->pcpu_stats) return -ENOMEM; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index cb7637364b40d85c9595da833873be1e99db3f7c..afd8b2a082454b57ccf51183e028e552fff1c91f 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -267,7 +267,6 @@ struct macsec_dev { struct pcpu_secy_stats __percpu *stats; struct list_head secys; struct gro_cells gro_cells; - unsigned int nest_level; }; /** @@ -2750,7 +2749,6 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, #define MACSEC_FEATURES \ (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) -static struct lock_class_key macsec_netdev_addr_lock_key; static int macsec_dev_init(struct net_device *dev) { @@ -2958,11 +2956,6 @@ static int macsec_get_iflink(const struct net_device *dev) return macsec_priv(dev)->real_dev->ifindex; } -static int macsec_get_nest_level(struct net_device *dev) -{ - return macsec_priv(dev)->nest_level; -} - static const struct net_device_ops macsec_netdev_ops = { .ndo_init = macsec_dev_init, .ndo_uninit = macsec_dev_uninit, @@ -2976,7 +2969,6 @@ static const struct net_device_ops macsec_netdev_ops = { .ndo_start_xmit = macsec_start_xmit, .ndo_get_stats64 = macsec_get_stats64, .ndo_get_iflink = macsec_get_iflink, - .ndo_get_lock_subclass = macsec_get_nest_level, }; static const struct device_type macsec_type = { @@ -3001,12 +2993,10 @@ static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = { static void macsec_free_netdev(struct net_device *dev) { struct macsec_dev *macsec = macsec_priv(dev); - struct net_device *real_dev = macsec->real_dev; free_percpu(macsec->stats); free_percpu(macsec->secy.tx_sc.stats); - dev_put(real_dev); } static void macsec_setup(struct net_device *dev) @@ -3261,14 +3251,6 @@ static int macsec_newlink(struct net *net, struct net_device *dev, if (err < 0) return err; - dev_hold(real_dev); - - macsec->nest_level = dev_get_nest_level(real_dev) + 1; - netdev_lockdep_set_classes(dev); - lockdep_set_class_and_subclass(&dev->addr_list_lock, - &macsec_netdev_addr_lock_key, - macsec_get_nest_level(dev)); - err = netdev_upper_dev_link(real_dev, dev, extack); if (err < 0) goto unregister; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 940192c057b6bdef4e7a0b7d6b7fe5ff2f4f78fa..34fc59bd1e20be52a6ea186a4c24ea94e4eb3882 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -852,8 +852,6 @@ static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) * "super class" of normal network devices; split their locks off into a * separate class since they always nest. */ -static struct lock_class_key macvlan_netdev_addr_lock_key; - #define ALWAYS_ON_OFFLOADS \ (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \ NETIF_F_GSO_ROBUST | NETIF_F_GSO_ENCAP_ALL) @@ -869,19 +867,6 @@ static struct lock_class_key macvlan_netdev_addr_lock_key; #define MACVLAN_STATE_MASK \ ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) -static int macvlan_get_nest_level(struct net_device *dev) -{ - return ((struct macvlan_dev *)netdev_priv(dev))->nest_level; -} - -static void macvlan_set_lockdep_class(struct net_device *dev) -{ - netdev_lockdep_set_classes(dev); - lockdep_set_class_and_subclass(&dev->addr_list_lock, - &macvlan_netdev_addr_lock_key, - macvlan_get_nest_level(dev)); -} - static int macvlan_init(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); @@ -900,8 +885,6 @@ static int macvlan_init(struct net_device *dev) dev->gso_max_segs = lowerdev->gso_max_segs; dev->hard_header_len = lowerdev->hard_header_len; - macvlan_set_lockdep_class(dev); - vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); if (!vlan->pcpu_stats) return -ENOMEM; @@ -1161,7 +1144,6 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_fdb_add = macvlan_fdb_add, .ndo_fdb_del = macvlan_fdb_del, .ndo_fdb_dump = ndo_dflt_fdb_dump, - .ndo_get_lock_subclass = macvlan_get_nest_level, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = macvlan_dev_poll_controller, .ndo_netpoll_setup = macvlan_dev_netpoll_setup, @@ -1445,7 +1427,6 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, vlan->dev = dev; vlan->port = port; vlan->set_features = MACVLAN_FEATURES; - vlan->nest_level = dev_get_nest_level(lowerdev) + 1; vlan->mode = MACVLAN_MODE_VEPA; if (data && data[IFLA_MACVLAN_MODE]) diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 56576d4f34a5e0d9f28734a1ab0c47be2ddd8fb2..54ca6681ba3182fa758f3eb1a6c768726ec92cb7 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -806,9 +806,11 @@ static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev) { struct nsim_dev_port *nsim_dev_port, *tmp; + mutex_lock(&nsim_dev->port_list_lock); list_for_each_entry_safe(nsim_dev_port, tmp, &nsim_dev->port_list, list) __nsim_dev_port_del(nsim_dev_port); + mutex_unlock(&nsim_dev->port_list_lock); } int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) @@ -822,14 +824,17 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) return PTR_ERR(nsim_dev); dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); + mutex_lock(&nsim_dev->port_list_lock); for (i = 0; i < nsim_bus_dev->port_count; i++) { err = __nsim_dev_port_add(nsim_dev, i); if (err) goto err_port_del_all; } + mutex_unlock(&nsim_dev->port_list_lock); return 0; err_port_del_all: + mutex_unlock(&nsim_dev->port_list_lock); nsim_dev_port_del_all(nsim_dev); nsim_dev_destroy(nsim_dev); return err; diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c index f61d094746c069bb7ac1c6db9eb77fe0820d2562..1a251f76d09b42082f2a9c5176314d256fe211b8 100644 --- a/drivers/net/netdevsim/fib.c +++ b/drivers/net/netdevsim/fib.c @@ -241,8 +241,8 @@ static struct pernet_operations nsim_fib_net_ops = { void nsim_fib_exit(void) { - unregister_pernet_subsys(&nsim_fib_net_ops); unregister_fib_notifier(&nsim_fib_nb); + unregister_pernet_subsys(&nsim_fib_net_ops); } int nsim_fib_init(void) @@ -258,6 +258,7 @@ int nsim_fib_init(void) err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent); if (err < 0) { pr_err("Failed to register fib notifier\n"); + unregister_pernet_subsys(&nsim_fib_net_ops); goto err_out; } diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 8fc33867e524f865261b68f8c2f74ab0d8c6d660..af8eabe7a6d4438876877b634f6a51f47449f691 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -572,6 +572,7 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev) .name = _name, \ /* PHY_BASIC_FEATURES */ \ .flags = PHY_IS_INTERNAL, \ + .soft_reset = genphy_soft_reset, \ .config_init = bcm7xxx_config_init, \ .suspend = bcm7xxx_suspend, \ .resume = bcm7xxx_config_init, \ diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 2fea5541c35a8a02910a09bbbaa0de7b9fcbc6c1..63dedec0433def38409d22df1b8db08ff2954005 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -341,6 +341,35 @@ static int ksz8041_config_aneg(struct phy_device *phydev) return genphy_config_aneg(phydev); } +static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev, + const u32 ksz_phy_id) +{ + int ret; + + if ((phydev->phy_id & MICREL_PHY_ID_MASK) != ksz_phy_id) + return 0; + + ret = phy_read(phydev, MII_BMSR); + if (ret < 0) + return ret; + + /* KSZ8051 PHY and KSZ8794/KSZ8795/KSZ8765 switch share the same + * exact PHY ID. However, they can be told apart by the extended + * capability registers presence. The KSZ8051 PHY has them while + * the switch does not. + */ + ret &= BMSR_ERCAP; + if (ksz_phy_id == PHY_ID_KSZ8051) + return ret; + else + return !ret; +} + +static int ksz8051_match_phy_device(struct phy_device *phydev) +{ + return ksz8051_ksz8795_match_phy_device(phydev, PHY_ID_KSZ8051); +} + static int ksz8081_config_init(struct phy_device *phydev) { /* KSZPHY_OMSO_FACTORY_TEST is set at de-assertion of the reset line @@ -364,6 +393,11 @@ static int ksz8061_config_init(struct phy_device *phydev) return kszphy_config_init(phydev); } +static int ksz8795_match_phy_device(struct phy_device *phydev) +{ + return ksz8051_ksz8795_match_phy_device(phydev, PHY_ID_KSZ87XX); +} + static int ksz9021_load_values_from_of(struct phy_device *phydev, const struct device_node *of_node, u16 reg, @@ -1017,8 +1051,6 @@ static struct phy_driver ksphy_driver[] = { .suspend = genphy_suspend, .resume = genphy_resume, }, { - .phy_id = PHY_ID_KSZ8051, - .phy_id_mask = MICREL_PHY_ID_MASK, .name = "Micrel KSZ8051", /* PHY_BASIC_FEATURES */ .driver_data = &ksz8051_type, @@ -1029,6 +1061,7 @@ static struct phy_driver ksphy_driver[] = { .get_sset_count = kszphy_get_sset_count, .get_strings = kszphy_get_strings, .get_stats = kszphy_get_stats, + .match_phy_device = ksz8051_match_phy_device, .suspend = genphy_suspend, .resume = genphy_resume, }, { @@ -1141,13 +1174,12 @@ static struct phy_driver ksphy_driver[] = { .suspend = genphy_suspend, .resume = genphy_resume, }, { - .phy_id = PHY_ID_KSZ8795, - .phy_id_mask = MICREL_PHY_ID_MASK, - .name = "Micrel KSZ8795", + .name = "Micrel KSZ87XX Switch", /* PHY_BASIC_FEATURES */ .config_init = kszphy_config_init, .config_aneg = ksz8873mll_config_aneg, .read_status = ksz8873mll_read_status, + .match_phy_device = ksz8795_match_phy_device, .suspend = genphy_suspend, .resume = genphy_resume, }, { diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 7935593debb11eaeec20a931350d64dc0746b82d..a1caeee1223617dab21b488858b14b5d0ef2aa2a 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -323,6 +323,8 @@ int genphy_c45_read_pma(struct phy_device *phydev) { int val; + linkmode_zero(phydev->lp_advertising); + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1); if (val < 0) return val; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 119e6f46605635000d5a4705207b3b58f189cb95..105d389b58e74512da4e424af100ba93855c0548 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -572,9 +572,6 @@ int phy_start_aneg(struct phy_device *phydev) if (AUTONEG_DISABLE == phydev->autoneg) phy_sanitize_settings(phydev); - /* Invalidate LP advertising flags */ - linkmode_zero(phydev->lp_advertising); - err = phy_config_aneg(phydev); if (err < 0) goto out_unlock; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9d2bbb13293ee0d32a1ad510dcb49bde44f3abf2..adb66a2fae18b3e54e671e497635ffcc2db803ba 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1787,7 +1787,14 @@ int genphy_read_lpa(struct phy_device *phydev) { int lpa, lpagb; - if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) { + if (phydev->autoneg == AUTONEG_ENABLE) { + if (!phydev->autoneg_complete) { + mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, + 0); + mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0); + return 0; + } + if (phydev->is_gigabit_capable) { lpagb = phy_read(phydev, MII_STAT1000); if (lpagb < 0) @@ -1815,6 +1822,8 @@ int genphy_read_lpa(struct phy_device *phydev) return lpa; mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); + } else { + linkmode_zero(phydev->lp_advertising); } return 0; diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index a5a57ca94c1ac541092867b685fe7d616218f96b..a578f7ebf715e69680b23e35c1aec90d33f200f4 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -87,8 +87,24 @@ struct phylink { phylink_printk(KERN_WARNING, pl, fmt, ##__VA_ARGS__) #define phylink_info(pl, fmt, ...) \ phylink_printk(KERN_INFO, pl, fmt, ##__VA_ARGS__) +#if defined(CONFIG_DYNAMIC_DEBUG) #define phylink_dbg(pl, fmt, ...) \ +do { \ + if ((pl)->config->type == PHYLINK_NETDEV) \ + netdev_dbg((pl)->netdev, fmt, ##__VA_ARGS__); \ + else if ((pl)->config->type == PHYLINK_DEV) \ + dev_dbg((pl)->dev, fmt, ##__VA_ARGS__); \ +} while (0) +#elif defined(DEBUG) +#define phylink_dbg(pl, fmt, ...) \ phylink_printk(KERN_DEBUG, pl, fmt, ##__VA_ARGS__) +#else +#define phylink_dbg(pl, fmt, ...) \ +({ \ + if (0) \ + phylink_printk(KERN_DEBUG, pl, fmt, ##__VA_ARGS__); \ +}) +#endif /** * phylink_set_port_modes() - set the port type modes in the ethtool mask @@ -576,7 +592,7 @@ static int phylink_register_sfp(struct phylink *pl, /** * phylink_create() - create a phylink instance - * @ndev: a pointer to the &struct net_device + * @config: a pointer to the target &struct phylink_config * @fwnode: a pointer to a &struct fwnode_handle describing the network * interface * @iface: the desired link mode defined by &typedef phy_interface_t diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index dc3d92d340c4d7a019c53706c96b0513cee13356..b732982507939563d08a49f7c6ec22d86f1b0dcf 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -327,6 +327,7 @@ static struct phy_driver smsc_phy_driver[] = { .name = "SMSC LAN8740", /* PHY_BASIC_FEATURES */ + .flags = PHY_RST_AFTER_CLK_EN, .probe = smsc_phy_probe, diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 9a1b006904a7dfa3ec5aa98c7cfd6b9a6d9c5a34..61824bbb55887232ce61c0d0b5f5bc304274ed3e 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -1324,8 +1324,6 @@ static int ppp_dev_init(struct net_device *dev) { struct ppp *ppp; - netdev_lockdep_set_classes(dev); - ppp = netdev_priv(dev); /* Let the netdevice take a reference on the ppp file. This ensures * that ppp_destroy_interface() won't run before the device gets diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index e8089def5a4671bad10efbde7b00297e4c37df69..8156b33ee3e7919188127c9ed7e732d89501eb66 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1615,7 +1615,6 @@ static int team_init(struct net_device *dev) int err; team->dev = dev; - mutex_init(&team->lock); team_set_no_mode(team); team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats); @@ -1642,7 +1641,8 @@ static int team_init(struct net_device *dev) goto err_options_register; netif_carrier_off(dev); - netdev_lockdep_set_classes(dev); + lockdep_register_key(&team->team_lock_key); + __mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key); return 0; @@ -1673,6 +1673,7 @@ static void team_uninit(struct net_device *dev) team_queue_override_fini(team); mutex_unlock(&team->lock); netdev_change_features(dev); + lockdep_unregister_key(&team->team_lock_key); } static void team_destructor(struct net_device *dev) @@ -1976,8 +1977,15 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev) err = team_port_del(team, port_dev); mutex_unlock(&team->lock); - if (!err) - netdev_change_features(dev); + if (err) + return err; + + if (netif_is_team_master(port_dev)) { + lockdep_unregister_key(&team->team_lock_key); + lockdep_register_key(&team->team_lock_key); + lockdep_set_class(&team->lock, &team->team_lock_key); + } + netdev_change_features(dev); return err; } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 812dc3a65efbb9d1ee2724e73978dbc4803ec171..a8d3141582a53caf407dc9aff61c452998de068f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -526,8 +526,8 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash, e = tun_flow_find(head, rxhash); if (likely(e)) { /* TODO: keep queueing to old queue until it's empty? */ - if (e->queue_index != queue_index) - e->queue_index = queue_index; + if (READ_ONCE(e->queue_index) != queue_index) + WRITE_ONCE(e->queue_index, queue_index); if (e->updated != jiffies) e->updated = jiffies; sock_rps_record_flow_hash(e->rps_rxhash); diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 32f53de5b1fe7abff0eb2882240bcd295977af08..fe630438f67b040e28e81675cb54a44b863acb83 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -787,6 +787,13 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index a505b2ab88b8a74f9bc2b737d4d22e6d9bbc080e..74849da031fab8f4944751b0fc78431fdfbbc8c8 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -186,7 +186,7 @@ struct hso_tiocmget { int intr_completed; struct usb_endpoint_descriptor *endp; struct urb *urb; - struct hso_serial_state_notification serial_state_notification; + struct hso_serial_state_notification *serial_state_notification; u16 prev_UART_state_bitmap; struct uart_icount icount; }; @@ -1432,7 +1432,7 @@ static int tiocmget_submit_urb(struct hso_serial *serial, usb_rcvintpipe(usb, tiocmget->endp-> bEndpointAddress & 0x7F), - &tiocmget->serial_state_notification, + tiocmget->serial_state_notification, sizeof(struct hso_serial_state_notification), tiocmget_intr_callback, serial, tiocmget->endp->bInterval); @@ -1479,7 +1479,7 @@ static void tiocmget_intr_callback(struct urb *urb) /* wIndex should be the USB interface number of the port to which the * notification applies, which should always be the Modem port. */ - serial_state_notification = &tiocmget->serial_state_notification; + serial_state_notification = tiocmget->serial_state_notification; if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE || serial_state_notification->bNotification != B_NOTIFICATION || le16_to_cpu(serial_state_notification->wValue) != W_VALUE || @@ -2565,6 +2565,8 @@ static void hso_free_tiomget(struct hso_serial *serial) usb_free_urb(tiocmget->urb); tiocmget->urb = NULL; serial->tiocmget = NULL; + kfree(tiocmget->serial_state_notification); + tiocmget->serial_state_notification = NULL; kfree(tiocmget); } } @@ -2615,10 +2617,13 @@ static struct hso_device *hso_create_bulk_serial_device( num_urbs = 2; serial->tiocmget = kzalloc(sizeof(struct hso_tiocmget), GFP_KERNEL); + serial->tiocmget->serial_state_notification + = kzalloc(sizeof(struct hso_serial_state_notification), + GFP_KERNEL); /* it isn't going to break our heart if serial->tiocmget * allocation fails don't bother checking this. */ - if (serial->tiocmget) { + if (serial->tiocmget && serial->tiocmget->serial_state_notification) { tiocmget = serial->tiocmget; tiocmget->endp = hso_get_ep(interface, USB_ENDPOINT_XFER_INT, diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 58f5a219fb65cdc8417ee9b19a1660b82f6f56c4..f24a1b0b801f032aec74d910c9e13ecec3559f80 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1264,8 +1264,11 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb) netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata); lan78xx_defer_kevent(dev, EVENT_LINK_RESET); - if (dev->domain_data.phyirq > 0) + if (dev->domain_data.phyirq > 0) { + local_irq_disable(); generic_handle_irq(dev->domain_data.phyirq); + local_irq_enable(); + } } else netdev_warn(dev->net, "unexpected interrupt: 0x%08x\n", intdata); @@ -3782,10 +3785,14 @@ static int lan78xx_probe(struct usb_interface *intf, /* driver requires remote-wakeup capability during autosuspend. */ intf->needs_remote_wakeup = 1; + ret = lan78xx_phy_init(dev); + if (ret < 0) + goto out4; + ret = register_netdev(netdev); if (ret != 0) { netif_err(dev, probe, netdev, "couldn't register the device\n"); - goto out4; + goto out5; } usb_set_intfdata(intf, dev); @@ -3798,14 +3805,10 @@ static int lan78xx_probe(struct usb_interface *intf, pm_runtime_set_autosuspend_delay(&udev->dev, DEFAULT_AUTOSUSPEND_DELAY); - ret = lan78xx_phy_init(dev); - if (ret < 0) - goto out5; - return 0; out5: - unregister_netdev(netdev); + phy_disconnect(netdev->phydev); out4: usb_free_urb(dev->urb_intr); out3: diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 3d77cd402ba9c6ad290557d4a57cc39e89b99440..596428ec71df6742d8b150e6c7076a79f477af94 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1327,6 +1327,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)}, /* Telit FN980 */ {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */ {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index cee9fef925cdc66052fb924d8ca96b89ddf2116a..d4a95b50bda6b22004472e74fcb7bd2faa4e55d9 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -5755,6 +5755,7 @@ static const struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0xa387)}, {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, {REALTEK_USB_DEVICE(VENDOR_ID_TPLINK, 0x0601)}, diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index c5d4a0060124cf238543b3c9f3f9de603749a708..681e0def6356ba8d4ea6a3c0d9982d09f3c9973b 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -335,7 +335,7 @@ static void sr_set_multicast(struct net_device *net) static int sr_mdio_read(struct net_device *net, int phy_id, int loc) { struct usbnet *dev = netdev_priv(net); - __le16 res; + __le16 res = 0; mutex_lock(&dev->phy_mutex); sr_set_sw_mii(dev); diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index ee52bde058df4bf20e2d720802476d3635d91393..b8228f50bc9412e8d6037510b0cc46df55369202 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -865,7 +865,6 @@ static int vrf_dev_init(struct net_device *dev) /* similarly, oper state is irrelevant; set to up to avoid confusion */ dev->operstate = IF_OPER_UP; - netdev_lockdep_set_classes(dev); return 0; out_rth: diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 3d9bcc957f7da15b58aad5d9cb6acdb9803f4553..8869154fad8895194a3a101f93119890a930c542 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2487,9 +2487,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, vni = tunnel_id_to_key32(info->key.tun_id); ifindex = 0; dst_cache = &info->dst_cache; - if (info->options_len && - info->key.tun_flags & TUNNEL_VXLAN_OPT) + if (info->key.tun_flags & TUNNEL_VXLAN_OPT) { + if (info->options_len < sizeof(*md)) + goto drop; md = ip_tunnel_info_opts(info); + } ttl = info->key.ttl; tos = info->key.tos; label = info->key.label; @@ -3566,10 +3568,13 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, { struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); + struct net_device *remote_dev = NULL; struct vxlan_fdb *f = NULL; bool unregister = false; + struct vxlan_rdst *dst; int err; + dst = &vxlan->default_dst; err = vxlan_dev_configure(net, dev, conf, false, extack); if (err) return err; @@ -3577,14 +3582,14 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, dev->ethtool_ops = &vxlan_ethtool_ops; /* create an fdb entry for a valid default destination */ - if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) { + if (!vxlan_addr_any(&dst->remote_ip)) { err = vxlan_fdb_create(vxlan, all_zeros_mac, - &vxlan->default_dst.remote_ip, + &dst->remote_ip, NUD_REACHABLE | NUD_PERMANENT, vxlan->cfg.dst_port, - vxlan->default_dst.remote_vni, - vxlan->default_dst.remote_vni, - vxlan->default_dst.remote_ifindex, + dst->remote_vni, + dst->remote_vni, + dst->remote_ifindex, NTF_SELF, &f); if (err) return err; @@ -3595,26 +3600,41 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, goto errout; unregister = true; + if (dst->remote_ifindex) { + remote_dev = __dev_get_by_index(net, dst->remote_ifindex); + if (!remote_dev) + goto errout; + + err = netdev_upper_dev_link(remote_dev, dev, extack); + if (err) + goto errout; + } + err = rtnl_configure_link(dev, NULL); if (err) - goto errout; + goto unlink; if (f) { - vxlan_fdb_insert(vxlan, all_zeros_mac, - vxlan->default_dst.remote_vni, f); + vxlan_fdb_insert(vxlan, all_zeros_mac, dst->remote_vni, f); /* notify default fdb entry */ err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, true, extack); if (err) { vxlan_fdb_destroy(vxlan, f, false, false); + if (remote_dev) + netdev_upper_dev_unlink(remote_dev, dev); goto unregister; } } list_add(&vxlan->next, &vn->vxlan_list); + if (remote_dev) + dst->remote_dev = remote_dev; return 0; - +unlink: + if (remote_dev) + netdev_upper_dev_unlink(remote_dev, dev); errout: /* unregister_netdevice() destroys the default FDB entry with deletion * notification. But the addition notification was not sent yet, so @@ -3932,11 +3952,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], struct netlink_ext_ack *extack) { struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_rdst *dst = &vxlan->default_dst; struct net_device *lowerdev; struct vxlan_config conf; + struct vxlan_rdst *dst; int err; + dst = &vxlan->default_dst; err = vxlan_nl2conf(tb, data, dev, &conf, true, extack); if (err) return err; @@ -3946,6 +3967,14 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], if (err) return err; + if (dst->remote_dev == lowerdev) + lowerdev = NULL; + + err = netdev_adjacent_change_prepare(dst->remote_dev, lowerdev, dev, + extack); + if (err) + return err; + /* handle default dst entry */ if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni); @@ -3962,6 +3991,8 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], NTF_SELF, true, extack); if (err) { spin_unlock_bh(&vxlan->hash_lock[hash_index]); + netdev_adjacent_change_abort(dst->remote_dev, + lowerdev, dev); return err; } } @@ -3979,6 +4010,11 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], if (conf.age_interval != vxlan->cfg.age_interval) mod_timer(&vxlan->age_timer, jiffies); + netdev_adjacent_change_commit(dst->remote_dev, lowerdev, dev); + if (lowerdev && lowerdev != dst->remote_dev) { + dst->remote_dev = lowerdev; + netdev_update_lockdep_key(lowerdev); + } vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); return 0; } @@ -3991,6 +4027,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head) list_del(&vxlan->next); unregister_netdevice_queue(dev, head); + if (vxlan->default_dst.remote_dev) + netdev_upper_dev_unlink(vxlan->default_dst.remote_dev, dev); } static size_t vxlan_get_size(const struct net_device *dev) diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c index 8efb493ceec2fc96cda43cb56cde5e6d19e91015..5c79f052cad20925c63e6c72adda3a97af3ee0fd 100644 --- a/drivers/net/wimax/i2400m/op-rfkill.c +++ b/drivers/net/wimax/i2400m/op-rfkill.c @@ -127,12 +127,12 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, "%d\n", result); result = 0; error_cmd: - kfree(cmd); kfree_skb(ack_skb); error_msg_to_dev: error_alloc: d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n", wimax_dev, state, result); + kfree(cmd); return result; } diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index dc45d16e8d21445f978e6831579a12a78357d57b..383d4fa555a889f16b642171b23301c1f3651132 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2118,12 +2118,15 @@ static int ath10k_init_uart(struct ath10k *ar) return ret; } - if (!uart_print && ar->hw_params.uart_pin_workaround) { - ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, - ar->hw_params.uart_pin); - if (ret) { - ath10k_warn(ar, "failed to set UART TX pin: %d", ret); - return ret; + if (!uart_print) { + if (ar->hw_params.uart_pin_workaround) { + ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, + ar->hw_params.uart_pin); + if (ret) { + ath10k_warn(ar, "failed to set UART TX pin: %d", + ret); + return ret; + } } return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 7573af2d88ce7cc8e35a45bcc050bac55a20d674..c2db758b9d54df6c9b6cf701f03cd8c879a08a51 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -162,12 +162,13 @@ int iwl_acpi_get_mcc(struct device *dev, char *mcc) wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE, &tbl_rev); - if (IS_ERR(wifi_pkg) || tbl_rev != 0) { + if (IS_ERR(wifi_pkg)) { ret = PTR_ERR(wifi_pkg); goto out_free; } - if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { + if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || + tbl_rev != 0) { ret = -EINVAL; goto out_free; } @@ -224,12 +225,13 @@ int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE, &tbl_rev); - if (IS_ERR(wifi_pkg) || tbl_rev != 0) { + if (IS_ERR(wifi_pkg)) { ret = PTR_ERR(wifi_pkg); goto out_free; } - if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { + if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || + tbl_rev != 0) { ret = -EINVAL; goto out_free; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 39c64850cb6f04ca25ff305a5cb4b9fe94d9584b..c0750ced5ac2952f6dec3965abefca731530c4db 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -520,7 +520,7 @@ struct iwl_scan_dwell { } __packed; /** - * struct iwl_scan_config + * struct iwl_scan_config_v1 * @flags: enum scan_config_flags * @tx_chains: valid_tx antenna - ANT_* definitions * @rx_chains: valid_rx antenna - ANT_* definitions @@ -552,7 +552,7 @@ struct iwl_scan_config_v1 { #define SCAN_LB_LMAC_IDX 0 #define SCAN_HB_LMAC_IDX 1 -struct iwl_scan_config { +struct iwl_scan_config_v2 { __le32 flags; __le32 tx_chains; __le32 rx_chains; @@ -564,6 +564,24 @@ struct iwl_scan_config { u8 bcast_sta_id; u8 channel_flags; u8 channel_array[]; +} __packed; /* SCAN_CONFIG_DB_CMD_API_S_2 */ + +/** + * struct iwl_scan_config + * @enable_cam_mode: whether to enable CAM mode. + * @enable_promiscouos_mode: whether to enable promiscouos mode + * @bcast_sta_id: the index of the station in the fw + * @reserved: reserved + * @tx_chains: valid_tx antenna - ANT_* definitions + * @rx_chains: valid_rx antenna - ANT_* definitions + */ +struct iwl_scan_config { + u8 enable_cam_mode; + u8 enable_promiscouos_mode; + u8 bcast_sta_id; + u8 reserved; + __le32 tx_chains; + __le32 rx_chains; } __packed; /* SCAN_CONFIG_DB_CMD_API_S_3 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 5c8602de9168992836dbdf9aa6f86586b88118d1..87421807e040b2756464293aa101082aa510cffb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -646,6 +646,7 @@ static struct scatterlist *alloc_sgtable(int size) if (new_page) __free_page(new_page); } + kfree(table); return NULL; } alloc_size = min_t(int, size, PAGE_SIZE); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 423cc0cf8e78139146664fd19d30d2a37f8e635b..0d5bc4ce5c072d0f4402f2dbd376f970f5409df3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -288,6 +288,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * STA_CONTEXT_DOT11AX_API_S * @IWL_UCODE_TLV_CAPA_SAR_TABLE_VER: This ucode supports different sar * version tables. + * @IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG: This ucode supports v3 of + * SCAN_CONFIG_DB_CMD_API_S. * * @NUM_IWL_UCODE_TLV_API: number of bits used */ @@ -321,6 +323,7 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE = (__force iwl_ucode_tlv_api_t)53, IWL_UCODE_TLV_API_FTM_RTT_ACCURACY = (__force iwl_ucode_tlv_api_t)54, IWL_UCODE_TLV_API_SAR_TABLE_VER = (__force iwl_ucode_tlv_api_t)55, + IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG = (__force iwl_ucode_tlv_api_t)56, IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57, IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER = (__force iwl_ucode_tlv_api_t)58, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index cb4c5514a55605c2d6215396244ab8b3f5daa514..695bbaa86273dd025f7d9322221ef2c439a97342 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -279,6 +279,7 @@ * Indicates MAC is entering a power-saving sleep power-down. * Not a good time to access device-internal resources. */ +#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) #define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) #define CSR_GP_CNTRL_REG_FLAG_XTAL_ON (0x00000400) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index f8e4f0f5de0c7251040627e39f8034dbb501bb4c..f09e368c7040c5868f0c2a076df262c4be3b0ded 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -112,38 +112,38 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf); */ static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs) { - return ofs + trans->cfg->trans.umac_prph_offset; + return ofs + trans->trans_cfg->umac_prph_offset; } static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) { return iwl_read_prph_no_grab(trans, ofs + - trans->cfg->trans.umac_prph_offset); + trans->trans_cfg->umac_prph_offset); } static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs) { - return iwl_read_prph(trans, ofs + trans->cfg->trans.umac_prph_offset); + return iwl_read_prph(trans, ofs + trans->trans_cfg->umac_prph_offset); } static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) { - iwl_write_prph_no_grab(trans, ofs + trans->cfg->trans.umac_prph_offset, + iwl_write_prph_no_grab(trans, ofs + trans->trans_cfg->umac_prph_offset, val); } static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs, u32 val) { - iwl_write_prph(trans, ofs + trans->cfg->trans.umac_prph_offset, val); + iwl_write_prph(trans, ofs + trans->trans_cfg->umac_prph_offset, val); } static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr, u32 bits, u32 mask, int timeout) { return iwl_poll_prph_bit(trans, addr + - trans->cfg->trans.umac_prph_offset, + trans->trans_cfg->umac_prph_offset, bits, mask, timeout); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index f47e0f97acf89d3c5d9bc483b7e2b75eefc4f8ec..23c25a7665f27087a58bd556de4c955e81e7cabd 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -449,6 +449,11 @@ enum { #define PERSISTENCE_BIT BIT(12) #define PREG_WFPM_ACCESS BIT(12) +#define HPM_HIPM_GEN_CFG 0xA03458 +#define HPM_HIPM_GEN_CFG_CR_PG_EN BIT(0) +#define HPM_HIPM_GEN_CFG_CR_SLP_EN BIT(1) +#define HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE BIT(10) + #define UREG_DOORBELL_TO_ISR6 0xA05C04 #define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0) #define UREG_DOORBELL_TO_ISR6_SUSPEND BIT(18) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 32a5e4e5461ff0a37e5282dff8285db42254ea64..d9eb2b2864383ffc59face511b5f888bee2ac0ff 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -420,6 +420,9 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) }; int ret; + if (mvm->trans->cfg->tx_with_siso_diversity) + init_cfg.init_flags |= cpu_to_le32(BIT(IWL_INIT_PHY)); + lockdep_assert_held(&mvm->mutex); mvm->rfkill_safe_init_done = false; @@ -694,12 +697,13 @@ static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm) wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev); - if (IS_ERR(wifi_pkg) || tbl_rev != 0) { + if (IS_ERR(wifi_pkg)) { ret = PTR_ERR(wifi_pkg); goto out_free; } - if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { + if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || + tbl_rev != 0) { ret = -EINVAL; goto out_free; } @@ -731,13 +735,14 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm) wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev); - if (IS_ERR(wifi_pkg) || tbl_rev != 0) { + if (IS_ERR(wifi_pkg)) { ret = PTR_ERR(wifi_pkg); goto out_free; } if ((wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) || - (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER)) { + (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) || + tbl_rev != 0) { ret = -EINVAL; goto out_free; } @@ -791,11 +796,16 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm) wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev); - if (IS_ERR(wifi_pkg) || tbl_rev > 1) { + if (IS_ERR(wifi_pkg)) { ret = PTR_ERR(wifi_pkg); goto out_free; } + if (tbl_rev != 0) { + ret = -EINVAL; + goto out_free; + } + mvm->geo_rev = tbl_rev; for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) { @@ -889,15 +899,17 @@ static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm) * firmware versions. Unfortunately, we don't have a TLV API * flag to rely on, so rely on the major version which is in * the first byte of ucode_ver. This was implemented - * initially on version 38 and then backported to29 and 17. - * The intention was to have it in 36 as well, but not all - * 8000 family got this feature enabled. The 8000 family is - * the only one using version 36, so skip this version - * entirely. + * initially on version 38 and then backported to 17. It was + * also backported to 29, but only for 7265D devices. The + * intention was to have it in 36 as well, but not all 8000 + * family got this feature enabled. The 8000 family is the + * only one using version 36, so skip this version entirely. */ return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 || - IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 || - IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17; + IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17 || + (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 && + ((mvm->trans->hw_rev & CSR_HW_REV_TYPE_MSK) == + CSR_HW_REV_TYPE_7265D)); } int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) @@ -1020,11 +1032,16 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev); - if (IS_ERR(wifi_pkg) || tbl_rev != 0) { + if (IS_ERR(wifi_pkg)) { ret = PTR_ERR(wifi_pkg); goto out_free; } + if (tbl_rev != 0) { + ret = -EINVAL; + goto out_free; + } + enabled = &wifi_pkg->package.elements[1]; if (enabled->type != ACPI_TYPE_INTEGER || (enabled->integer.value != 0 && enabled->integer.value != 1)) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index cd1b10042fbfc8cb55cf025d1285dfd85f67372c..d31f96c3f9251a2256bab9e181796e91289147cd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -4881,11 +4881,11 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, if (!iwl_mvm_has_new_rx_api(mvm)) return; - notif->cookie = mvm->queue_sync_cookie; - - if (notif->sync) + if (notif->sync) { + notif->cookie = mvm->queue_sync_cookie; atomic_set(&mvm->queue_sync_counter, mvm->trans->num_rx_queues); + } ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size, !notif->sync); @@ -4905,7 +4905,8 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, out: atomic_set(&mvm->queue_sync_counter, 0); - mvm->queue_sync_cookie++; + if (notif->sync) + mvm->queue_sync_cookie++; } static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 843d00bf2bd55504d057075871968291f9897a3a..5ca50f39a023db3f5af56519ea9f135b74a204a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1405,6 +1405,12 @@ static inline bool iwl_mvm_is_scan_ext_chan_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER); } +static inline bool iwl_mvm_is_reduced_config_scan_supported(struct iwl_mvm *mvm) +{ + return fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG); +} + static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm) { return fw_has_api(&mvm->fw->ucode_capa, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index f6b3045badbdec548b695c39e8744f6a1f3e9ced..fcafa22ec6ce222878a29496f6940347fe5620f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1137,11 +1137,11 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels); } -static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, - u32 flags, u8 channel_flags, - u32 max_channels) +static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config, + u32 flags, u8 channel_flags, + u32 max_channels) { - struct iwl_scan_config *cfg = config; + struct iwl_scan_config_v2 *cfg = config; cfg->flags = cpu_to_le32(flags); cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); @@ -1185,7 +1185,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels); } -int iwl_mvm_config_scan(struct iwl_mvm *mvm) +static int iwl_mvm_legacy_config_scan(struct iwl_mvm *mvm) { void *cfg; int ret, cmd_size; @@ -1217,7 +1217,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) } if (iwl_mvm_cdb_scan_api(mvm)) - cmd_size = sizeof(struct iwl_scan_config); + cmd_size = sizeof(struct iwl_scan_config_v2); else cmd_size = sizeof(struct iwl_scan_config_v1); cmd_size += num_channels; @@ -1254,8 +1254,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ? SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED : SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED; - iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags, - num_channels); + iwl_mvm_fill_scan_config_v2(mvm, cfg, flags, channel_flags, + num_channels); } else { iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags, num_channels); @@ -1277,6 +1277,30 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) return ret; } +int iwl_mvm_config_scan(struct iwl_mvm *mvm) +{ + struct iwl_scan_config cfg; + struct iwl_host_cmd cmd = { + .id = iwl_cmd_id(SCAN_CFG_CMD, IWL_ALWAYS_LONG_GROUP, 0), + .len[0] = sizeof(cfg), + .data[0] = &cfg, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; + + if (!iwl_mvm_is_reduced_config_scan_supported(mvm)) + return iwl_mvm_legacy_config_scan(mvm); + + memset(&cfg, 0, sizeof(cfg)); + + cfg.bcast_sta_id = mvm->aux_sta.sta_id; + cfg.tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); + cfg.rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm)); + + IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n"); + + return iwl_mvm_send_cmd(mvm, &cmd); +} + static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status) { int i; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 0bedba4c61f2ae898c7ddbb612d041e9c9fdd7dc..b3768d5d852ae367394630a9e4d72d03b28ab2a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1482,6 +1482,13 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, mvm_sta->sta_id, i); txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id, i, wdg); + /* + * on failures, just set it to IWL_MVM_INVALID_QUEUE + * to try again later, we have no other good way of + * failing here + */ + if (txq_id < 0) + txq_id = IWL_MVM_INVALID_QUEUE; tid_data->txq_id = txq_id; /* @@ -1950,30 +1957,73 @@ void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta) sta->sta_id = IWL_MVM_INVALID_STA; } -static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue, +static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue, u8 sta_id, u8 fifo) { unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? mvm->trans->trans_cfg->base_params->wd_timeout : IWL_WATCHDOG_DISABLED; + struct iwl_trans_txq_scd_cfg cfg = { + .fifo = fifo, + .sta_id = sta_id, + .tid = IWL_MAX_TID_COUNT, + .aggregate = false, + .frame_limit = IWL_FRAME_LIMIT, + }; + + WARN_ON(iwl_mvm_has_new_tx_api(mvm)); + + iwl_mvm_enable_txq(mvm, NULL, queue, 0, &cfg, wdg_timeout); +} + +static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id) +{ + unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? + mvm->trans->trans_cfg->base_params->wd_timeout : + IWL_WATCHDOG_DISABLED; + + WARN_ON(!iwl_mvm_has_new_tx_api(mvm)); + + return iwl_mvm_tvqm_enable_txq(mvm, sta_id, IWL_MAX_TID_COUNT, + wdg_timeout); +} +static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx, + int maccolor, + struct iwl_mvm_int_sta *sta, + u16 *queue, int fifo) +{ + int ret; + + /* Map queue to fifo - needs to happen before adding station */ + if (!iwl_mvm_has_new_tx_api(mvm)) + iwl_mvm_enable_aux_snif_queue(mvm, *queue, sta->sta_id, fifo); + + ret = iwl_mvm_add_int_sta_common(mvm, sta, NULL, macidx, maccolor); + if (ret) { + if (!iwl_mvm_has_new_tx_api(mvm)) + iwl_mvm_disable_txq(mvm, NULL, *queue, + IWL_MAX_TID_COUNT, 0); + return ret; + } + + /* + * For 22000 firmware and on we cannot add queue to a station unknown + * to firmware so enable queue here - after the station was added + */ if (iwl_mvm_has_new_tx_api(mvm)) { - int tvqm_queue = - iwl_mvm_tvqm_enable_txq(mvm, sta_id, - IWL_MAX_TID_COUNT, - wdg_timeout); - *queue = tvqm_queue; - } else { - struct iwl_trans_txq_scd_cfg cfg = { - .fifo = fifo, - .sta_id = sta_id, - .tid = IWL_MAX_TID_COUNT, - .aggregate = false, - .frame_limit = IWL_FRAME_LIMIT, - }; + int txq; - iwl_mvm_enable_txq(mvm, NULL, *queue, 0, &cfg, wdg_timeout); + txq = iwl_mvm_enable_aux_snif_queue_tvqm(mvm, sta->sta_id); + if (txq < 0) { + iwl_mvm_rm_sta_common(mvm, sta->sta_id); + return txq; + } + + *queue = txq; } + + return 0; } int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) @@ -1989,59 +2039,26 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) if (ret) return ret; - /* Map Aux queue to fifo - needs to happen before adding Aux station */ - if (!iwl_mvm_has_new_tx_api(mvm)) - iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue, - mvm->aux_sta.sta_id, - IWL_MVM_TX_FIFO_MCAST); - - ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL, - MAC_INDEX_AUX, 0); + ret = iwl_mvm_add_int_sta_with_queue(mvm, MAC_INDEX_AUX, 0, + &mvm->aux_sta, &mvm->aux_queue, + IWL_MVM_TX_FIFO_MCAST); if (ret) { iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta); return ret; } - /* - * For 22000 firmware and on we cannot add queue to a station unknown - * to firmware so enable queue here - after the station was added - */ - if (iwl_mvm_has_new_tx_api(mvm)) - iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue, - mvm->aux_sta.sta_id, - IWL_MVM_TX_FIFO_MCAST); - return 0; } int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - int ret; lockdep_assert_held(&mvm->mutex); - /* Map snif queue to fifo - must happen before adding snif station */ - if (!iwl_mvm_has_new_tx_api(mvm)) - iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue, - mvm->snif_sta.sta_id, + return iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color, + &mvm->snif_sta, &mvm->snif_queue, IWL_MVM_TX_FIFO_BE); - - ret = iwl_mvm_add_int_sta_common(mvm, &mvm->snif_sta, vif->addr, - mvmvif->id, 0); - if (ret) - return ret; - - /* - * For 22000 firmware and on we cannot add queue to a station unknown - * to firmware so enable queue here - after the station was added - */ - if (iwl_mvm_has_new_tx_api(mvm)) - iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue, - mvm->snif_sta.sta_id, - IWL_MVM_TX_FIFO_BE); - - return 0; } int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -2133,6 +2150,10 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id, IWL_MAX_TID_COUNT, wdg_timeout); + if (queue < 0) { + iwl_mvm_rm_sta_common(mvm, bsta->sta_id); + return queue; + } if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) @@ -2307,10 +2328,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) } ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr, mvmvif->id, mvmvif->color); - if (ret) { - iwl_mvm_dealloc_int_sta(mvm, msta); - return ret; - } + if (ret) + goto err; /* * Enable cab queue after the ADD_STA command is sent. @@ -2323,6 +2342,10 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id, 0, timeout); + if (queue < 0) { + ret = queue; + goto err; + } mvmvif->cab_queue = queue; } else if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) @@ -2330,6 +2353,9 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) timeout); return 0; +err: + iwl_mvm_dealloc_int_sta(mvm, msta); + return ret; } static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 75fa8a6aafeec951e71408fa166b47014fdddb49..74980382e64c89e1def4e1106a5439488a858ea9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -107,13 +107,9 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, /* allocate ucode sections in dram and set addresses */ ret = iwl_pcie_init_fw_sec(trans, fw, &prph_scratch->dram); - if (ret) { - dma_free_coherent(trans->dev, - sizeof(*prph_scratch), - prph_scratch, - trans_pcie->prph_scratch_dma_addr); - return ret; - } + if (ret) + goto err_free_prph_scratch; + /* Allocate prph information * currently we don't assign to the prph info anything, but it would get @@ -121,16 +117,20 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, prph_info = dma_alloc_coherent(trans->dev, sizeof(*prph_info), &trans_pcie->prph_info_dma_addr, GFP_KERNEL); - if (!prph_info) - return -ENOMEM; + if (!prph_info) { + ret = -ENOMEM; + goto err_free_prph_scratch; + } /* Allocate context info */ ctxt_info_gen3 = dma_alloc_coherent(trans->dev, sizeof(*ctxt_info_gen3), &trans_pcie->ctxt_info_dma_addr, GFP_KERNEL); - if (!ctxt_info_gen3) - return -ENOMEM; + if (!ctxt_info_gen3) { + ret = -ENOMEM; + goto err_free_prph_info; + } ctxt_info_gen3->prph_info_base_addr = cpu_to_le64(trans_pcie->prph_info_dma_addr); @@ -186,6 +186,20 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); return 0; + +err_free_prph_info: + dma_free_coherent(trans->dev, + sizeof(*prph_info), + prph_info, + trans_pcie->prph_info_dma_addr); + +err_free_prph_scratch: + dma_free_coherent(trans->dev, + sizeof(*prph_scratch), + prph_scratch, + trans_pcie->prph_scratch_dma_addr); + return ret; + } void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index e29c47744ef59bca551103278b409c4ae09ac2a2..040cec17d3ad68c4e2d38ee1af19f686c1bbc90e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -513,31 +513,33 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x24FD, 0x9074, iwl8265_2ac_cfg)}, /* 9000 Series */ - {IWL_PCI_DEVICE(0x02F0, 0x0030, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0034, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0060, iwl9461_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0064, iwl9461_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x00A0, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x00A4, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0230, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0234, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0238, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x023C, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0260, iwl9461_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0264, iwl9461_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x02A0, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x02A4, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x1551, iwl9560_killer_s_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x1552, iwl9560_killer_i_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x2030, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x2034, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x4030, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x4034, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x40A4, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x4234, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x42A4, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x00A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0230, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x1030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x06F0, 0x0030, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0034, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc)}, @@ -571,20 +573,20 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0060, iwl9460_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0064, iwl9460_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9460_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x00A4, iwl9460_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0060, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x0064, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x00A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x0210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0214, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0230, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0234, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0238, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x023C, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0260, iwl9460_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x02A0, iwl9460_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x02A4, iwl9460_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x02A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x02A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x1010, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x1030, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x1210, iwl9260_2ac_cfg)}, @@ -601,7 +603,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x6010, iwl9260_2ac_160_cfg)}, @@ -616,33 +618,33 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0214, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x271C, 0x0214, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x0230, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x1030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_160_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_soc)}, + + {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x00A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0230, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x1030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_160_cfg_soc)}, @@ -671,6 +673,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x30DC, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_160_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_160_cfg_shared_clk)}, @@ -726,62 +729,60 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x34F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0038, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x003C, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0060, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0230, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0238, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x023C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x3DF0, 0x1030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x3DF0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x4030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0230, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0238, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x023C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x43F0, 0x1030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x43F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x4030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x00A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0230, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x1030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x3DF0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + + {IWL_PCI_DEVICE(0x43F0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x00A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0230, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x1030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0030, iwl9560_2ac_160_cfg_soc)}, @@ -821,34 +822,34 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x9DF0, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0230, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0238, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x023C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0xA0F0, 0x1030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0xA0F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x4030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x42A4, iwl9462_2ac_cfg_soc)}, + + {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x00A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0230, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0xA370, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_160_cfg_soc)}, @@ -1067,11 +1068,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && - ((cfg != &iwl_ax200_cfg_cc && - cfg != &killer1650x_2ax_cfg && - cfg != &killer1650w_2ax_cfg && - cfg != &iwl_ax201_cfg_quz_hr) || - iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) { + iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) { u32 hw_status; hw_status = iwl_read_prph(iwl_trans, UMAG_GEN_HW_STATUS); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index df8455f14e4d82462238de74a9b3f4ea664ccfe0..ca3bb4d65b00e2ff99421cf867f2812a4f2da563 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -57,6 +57,24 @@ #include "internal.h" #include "fw/dbg.h" +static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans) +{ + iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG, + HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE); + udelay(20); + iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG, + HPM_HIPM_GEN_CFG_CR_PG_EN | + HPM_HIPM_GEN_CFG_CR_SLP_EN); + udelay(20); + iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG, + HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE); + + iwl_trans_sw_reset(trans); + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + + return 0; +} + /* * Start up NIC's basic functionality after it has been reset * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop()) @@ -92,6 +110,13 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans) iwl_pcie_apm_config(trans); + if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 && + trans->cfg->integrated) { + ret = iwl_pcie_gen2_force_power_gating(trans); + if (ret) + return ret; + } + ret = iwl_finish_nic_init(trans, trans->trans_cfg); if (ret) return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f8a1f985a1d85e0dd70a60a2cda12c5975714fe0..6961f00ff81219a31decbbd9ec733f1532b85a59 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3272,11 +3272,17 @@ static struct iwl_trans_dump_data ptr = cmdq->write_ptr; for (i = 0; i < cmdq->n_window; i++) { u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr); + u8 tfdidx; u32 caplen, cmdlen; + if (trans->trans_cfg->use_tfh) + tfdidx = idx; + else + tfdidx = ptr; + cmdlen = iwl_trans_pcie_get_cmdlen(trans, - cmdq->tfds + - tfd_size * ptr); + (u8 *)cmdq->tfds + + tfd_size * tfdidx); caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen); if (cmdlen) { @@ -3450,6 +3456,15 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, spin_lock_init(&trans_pcie->reg_lock); mutex_init(&trans_pcie->mutex); init_waitqueue_head(&trans_pcie->ucode_write_waitq); + + trans_pcie->rba.alloc_wq = alloc_workqueue("rb_allocator", + WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!trans_pcie->rba.alloc_wq) { + ret = -ENOMEM; + goto out_free_trans; + } + INIT_WORK(&trans_pcie->rba.rx_alloc, iwl_pcie_rx_allocator_work); + trans_pcie->tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); if (!trans_pcie->tso_hdr_page) { ret = -ENOMEM; @@ -3584,10 +3599,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->inta_mask = CSR_INI_SET_MASK; } - trans_pcie->rba.alloc_wq = alloc_workqueue("rb_allocator", - WQ_HIGHPRI | WQ_UNBOUND, 1); - INIT_WORK(&trans_pcie->rba.rx_alloc, iwl_pcie_rx_allocator_work); - #ifdef CONFIG_IWLWIFI_DEBUGFS trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_CLOSED; mutex_init(&trans_pcie->fw_mon_data.mutex); @@ -3599,6 +3610,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, iwl_pcie_free_ict(trans); out_no_pci: free_percpu(trans_pcie->tso_hdr_page); + destroy_workqueue(trans_pcie->rba.alloc_wq); +out_free_trans: iwl_trans_free(trans); return ERR_PTR(ret); } diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c index 158a3d762e55d6e31afd2c358c81f7d93f7264c6..e323e9a5999fd5a307ec8609044cb553db65682f 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_hw.c +++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c @@ -3041,30 +3041,6 @@ static void prism2_clear_set_tim_queue(local_info_t *local) } } - -/* - * HostAP uses two layers of net devices, where the inner - * layer gets called all the time from the outer layer. - * This is a natural nesting, which needs a split lock type. - */ -static struct lock_class_key hostap_netdev_xmit_lock_key; -static struct lock_class_key hostap_netdev_addr_lock_key; - -static void prism2_set_lockdep_class_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, - &hostap_netdev_xmit_lock_key); -} - -static void prism2_set_lockdep_class(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, - &hostap_netdev_addr_lock_key); - netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL); -} - static struct net_device * prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, struct device *sdev) @@ -3223,7 +3199,6 @@ while (0) if (ret >= 0) ret = register_netdevice(dev); - prism2_set_lockdep_class(dev); rtnl_unlock(); if (ret < 0) { printk(KERN_WARNING "%s: register netdevice failed!\n", diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 45c73a6f09a128a8ef069906b1e02aaf144ffaea..14f562cd715c0b8d27eb0fb21a08ccecbc416a01 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -4026,7 +4026,7 @@ static int __init init_mac80211_hwsim(void) err = dev_alloc_name(hwsim_mon, hwsim_mon->name); if (err < 0) { rtnl_unlock(); - goto out_free_radios; + goto out_free_mon; } err = register_netdevice(hwsim_mon); diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 4d03596e891f11c66ff6cb011d3f4a39830fff1b..d7a1ddc9e40742a718337e7e35201eb8f81c079f 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -8,6 +8,8 @@ mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ tx.o agg-rx.o mcu.o +mt76-$(CONFIG_PCI) += pci.o + mt76-usb-y := usb.o usb_trace.o CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index c747eb24581c42683f93f6e285a660e2edd9daea..8f69d00bd940a98aaa84a0166c7375357ecab82a 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -53,8 +53,10 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, u32 ctrl; int i, idx = -1; - if (txwi) + if (txwi) { q->entry[q->head].txwi = DMA_DUMMY_DATA; + q->entry[q->head].skip_buf0 = true; + } for (i = 0; i < nbufs; i += 2, buf += 2) { u32 buf0 = buf[0].addr, buf1 = 0; @@ -97,7 +99,7 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, __le32 __ctrl = READ_ONCE(q->desc[idx].ctrl); u32 ctrl = le32_to_cpu(__ctrl); - if (!e->txwi || !e->skb) { + if (!e->skip_buf0) { __le32 addr = READ_ONCE(q->desc[idx].buf0); u32 len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 570c159515a09cae82d2e17cd74324cea5132cd5..8aec7ccf2d79b45ccbcd9388ab72e97e4c98bb2c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -93,8 +93,9 @@ struct mt76_queue_entry { struct urb *urb; }; enum mt76_txq_id qid; - bool schedule; - bool done; + bool skip_buf0:1; + bool schedule:1; + bool done:1; }; struct mt76_queue_regs { @@ -578,6 +579,7 @@ bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, #define mt76_poll_msec(dev, ...) __mt76_poll_msec(&((dev)->mt76), __VA_ARGS__) void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs); +void mt76_pci_disable_aspm(struct pci_dev *pdev); static inline u16 mt76_chip(struct mt76_dev *dev) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 73c3104f88582bbdefca26fb44b86f765248642e..cf611d1b817c07dd5179c1dc2aa0182975904a3f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -81,6 +81,8 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* RG_SSUSB_CDR_BR_PE1D = 0x3 */ mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3); + mt76_pci_disable_aspm(pdev); + return 0; error: diff --git a/drivers/net/wireless/mediatek/mt76/pci.c b/drivers/net/wireless/mediatek/mt76/pci.c new file mode 100644 index 0000000000000000000000000000000000000000..04c5a692bc852acb588d6e47706fb397af6c0845 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/pci.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2019 Lorenzo Bianconi + */ + +#include + +void mt76_pci_disable_aspm(struct pci_dev *pdev) +{ + struct pci_dev *parent = pdev->bus->self; + u16 aspm_conf, parent_aspm_conf = 0; + + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf); + aspm_conf &= PCI_EXP_LNKCTL_ASPMC; + if (parent) { + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, + &parent_aspm_conf); + parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC; + } + + if (!aspm_conf && (!parent || !parent_aspm_conf)) { + /* aspm already disabled */ + return; + } + + dev_info(&pdev->dev, "disabling ASPM %s %s\n", + (aspm_conf & PCI_EXP_LNKCTL_ASPM_L0S) ? "L0s" : "", + (aspm_conf & PCI_EXP_LNKCTL_ASPM_L1) ? "L1" : ""); + + if (IS_ENABLED(CONFIG_PCIEASPM)) { + int err; + + err = pci_disable_link_state(pdev, aspm_conf); + if (!err) + return; + } + + /* both device and parent should have the same ASPM setting. + * disable ASPM in downstream component first and then upstream. + */ + pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_conf); + if (parent) + pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, + aspm_conf); +} +EXPORT_SYMBOL_GPL(mt76_pci_disable_aspm); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 2b216edd0c7d2cbecb10ca1ec46834910538cbed..a90a518b40d368f9a3da741ea8efade3e5ef2791 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index 4d4e3888ef2080379509f8b12f5af9409a3b5c3e..f2395309ec006a60ecea426992cab9e50a86d75f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c @@ -555,7 +555,7 @@ static ssize_t rt2x00debug_write_restart_hw(struct file *file, { struct rt2x00debug_intf *intf = file->private_data; struct rt2x00_dev *rt2x00dev = intf->rt2x00dev; - static unsigned long last_reset; + static unsigned long last_reset = INITIAL_JIFFIES; if (!rt2x00_has_cap_restart_hw(rt2x00dev)) return -EOPNOTSUPP; diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 6087ec7a90a6e6ad5d2ac1921beadd243780f866..f88d26535978d958b6b21eba521e446786b87b10 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -822,7 +822,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) hdr = rtl_get_hdr(skb); fc = rtl_get_fc(skb); - if (!stats.crc && !stats.hwerror) { + if (!stats.crc && !stats.hwerror && (skb->len > FCS_LEN)) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); @@ -859,6 +859,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) _rtl_pci_rx_to_mac80211(hw, skb, rx_status); } } else { + /* drop packets with errors or those too short */ dev_kfree_skb_any(skb); } new_trx_end: diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index 70f04c2f5b176ffe8a8178fb02cbbffbdd4a2990..fff8dda14023861158acc10bea9f6df2b203d2f6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/ps.c +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c @@ -754,6 +754,9 @@ static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, return; } else { noa_num = (noa_len - 2) / 13; + if (noa_num > P2P_MAX_NOA_NUM) + noa_num = P2P_MAX_NOA_NUM; + } noa_index = ie[3]; if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == @@ -848,6 +851,9 @@ static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, return; } else { noa_num = (noa_len - 2) / 13; + if (noa_num > P2P_MAX_NOA_NUM) + noa_num = P2P_MAX_NOA_NUM; + } noa_index = ie[3]; if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index be92e1220284c7d07d2b8143f5b8084e1d9375da..07c43e4b750b62322b9f82a250667b3f3f87aa9f 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -13,6 +13,7 @@ #include #include #include +#include static struct wiphy *common_wiphy; @@ -20,6 +21,7 @@ struct virt_wifi_wiphy_priv { struct delayed_work scan_result; struct cfg80211_scan_request *scan_request; bool being_deleted; + struct virt_wifi_network_simulation *network_simulation; }; static struct ieee80211_channel channel_2ghz = { @@ -148,6 +150,9 @@ static int virt_wifi_scan(struct wiphy *wiphy, priv->scan_request = request; schedule_delayed_work(&priv->scan_result, HZ * 2); + if (priv->network_simulation && + priv->network_simulation->notify_scan_trigger) + priv->network_simulation->notify_scan_trigger(wiphy, request); return 0; } @@ -178,6 +183,12 @@ static void virt_wifi_scan_result(struct work_struct *work) DBM_TO_MBM(-50), GFP_KERNEL); cfg80211_put_bss(wiphy, informed_bss); + if(priv->network_simulation && + priv->network_simulation->generate_virt_scan_result) { + if(priv->network_simulation->generate_virt_scan_result(wiphy)) + wiphy_err(wiphy, "Fail to generater the simulated scan result.\n"); + } + /* Schedules work which acquires and releases the rtnl lock. */ cfg80211_scan_done(priv->scan_request, &scan_info); priv->scan_request = NULL; @@ -365,6 +376,8 @@ static struct wiphy *virt_wifi_make_wiphy(void) priv = wiphy_priv(wiphy); priv->being_deleted = false; priv->scan_request = NULL; + priv->network_simulation = NULL; + INIT_DELAYED_WORK(&priv->scan_result, virt_wifi_scan_result); err = wiphy_register(wiphy); @@ -380,7 +393,6 @@ static struct wiphy *virt_wifi_make_wiphy(void) static void virt_wifi_destroy_wiphy(struct wiphy *wiphy) { struct virt_wifi_wiphy_priv *priv; - WARN(!wiphy, "%s called with null wiphy", __func__); if (!wiphy) return; @@ -414,8 +426,13 @@ static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb, static int virt_wifi_net_device_open(struct net_device *dev) { struct virt_wifi_netdev_priv *priv = netdev_priv(dev); - + struct virt_wifi_wiphy_priv *w_priv; priv->is_up = true; + w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + if(w_priv->network_simulation && + w_priv->network_simulation->notify_device_open) + w_priv->network_simulation->notify_device_open(dev); + return 0; } @@ -423,16 +440,22 @@ static int virt_wifi_net_device_open(struct net_device *dev) static int virt_wifi_net_device_stop(struct net_device *dev) { struct virt_wifi_netdev_priv *n_priv = netdev_priv(dev); + struct virt_wifi_wiphy_priv *w_priv; n_priv->is_up = false; if (!dev->ieee80211_ptr) return 0; + w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy); virt_wifi_cancel_scan(dev->ieee80211_ptr->wiphy); virt_wifi_cancel_connect(dev); netif_carrier_off(dev); + if (w_priv->network_simulation && + w_priv->network_simulation->notify_device_stop) + w_priv->network_simulation->notify_device_stop(dev); + return 0; } @@ -548,6 +571,7 @@ static int virt_wifi_newlink(struct net *src_net, struct net_device *dev, priv->is_connected = false; priv->is_up = false; INIT_DELAYED_WORK(&priv->connect, virt_wifi_connect_complete); + __module_get(THIS_MODULE); return 0; unregister_netdev: @@ -578,6 +602,7 @@ static void virt_wifi_dellink(struct net_device *dev, netdev_upper_dev_unlink(priv->lowerdev, dev); unregister_netdevice_queue(dev, head); + module_put(THIS_MODULE); /* Deleting the wiphy is handled in the module destructor. */ } @@ -590,6 +615,42 @@ static struct rtnl_link_ops virt_wifi_link_ops = { .priv_size = sizeof(struct virt_wifi_netdev_priv), }; +static bool netif_is_virt_wifi_dev(const struct net_device *dev) +{ + return rcu_access_pointer(dev->rx_handler) == virt_wifi_rx_handler; +} + +static int virt_wifi_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + struct net_device *lower_dev = netdev_notifier_info_to_dev(ptr); + struct virt_wifi_netdev_priv *priv; + struct net_device *upper_dev; + LIST_HEAD(list_kill); + + if (!netif_is_virt_wifi_dev(lower_dev)) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_UNREGISTER: + priv = rtnl_dereference(lower_dev->rx_handler_data); + if (!priv) + return NOTIFY_DONE; + + upper_dev = priv->upperdev; + + upper_dev->rtnl_link_ops->dellink(upper_dev, &list_kill); + unregister_netdevice_many(&list_kill); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block virt_wifi_notifier = { + .notifier_call = virt_wifi_event, +}; + /* Acquires and releases the rtnl lock. */ static int __init virt_wifi_init_module(void) { @@ -598,14 +659,25 @@ static int __init virt_wifi_init_module(void) /* Guaranteed to be locallly-administered and not multicast. */ eth_random_addr(fake_router_bssid); + err = register_netdevice_notifier(&virt_wifi_notifier); + if (err) + return err; + + err = -ENOMEM; common_wiphy = virt_wifi_make_wiphy(); if (!common_wiphy) - return -ENOMEM; + goto notifier; err = rtnl_link_register(&virt_wifi_link_ops); if (err) - virt_wifi_destroy_wiphy(common_wiphy); + goto destroy_wiphy; + + return 0; +destroy_wiphy: + virt_wifi_destroy_wiphy(common_wiphy); +notifier: + unregister_netdevice_notifier(&virt_wifi_notifier); return err; } @@ -615,7 +687,29 @@ static void __exit virt_wifi_cleanup_module(void) /* Will delete any devices that depend on the wiphy. */ rtnl_link_unregister(&virt_wifi_link_ops); virt_wifi_destroy_wiphy(common_wiphy); + unregister_netdevice_notifier(&virt_wifi_notifier); +} + +int virt_wifi_register_network_simulation + (struct virt_wifi_network_simulation *ops) +{ + struct virt_wifi_wiphy_priv *priv = wiphy_priv(common_wiphy); + if (priv->network_simulation) + return -EEXIST; + priv->network_simulation = ops; + return 0; +} +EXPORT_SYMBOL(virt_wifi_register_network_simulation); + +int virt_wifi_unregister_network_simulation(void) +{ + struct virt_wifi_wiphy_priv *priv = wiphy_priv(common_wiphy); + if(!priv->network_simulation) + return -ENODATA; + priv->network_simulation = NULL; + return 0; } +EXPORT_SYMBOL(virt_wifi_unregister_network_simulation); module_init(virt_wifi_init_module); module_exit(virt_wifi_cleanup_module); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 240f762b374953b94cf8855823e4f10d9ff91944..103ed00775eb4a608220067a54f09a909f255e71 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -719,7 +719,6 @@ int xenvif_connect_data(struct xenvif_queue *queue, xenvif_unmap_frontend_data_rings(queue); netif_napi_del(&queue->napi); err: - module_put(THIS_MODULE); return err; } diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c index c5289eaf17eef7f65a09cf478dc7b7e8d29592bd..e897e4d768ef7968032a1614fe3a207ed5190795 100644 --- a/drivers/nfc/pn533/usb.c +++ b/drivers/nfc/pn533/usb.c @@ -547,18 +547,25 @@ static int pn533_usb_probe(struct usb_interface *interface, rc = pn533_finalize_setup(priv); if (rc) - goto error; + goto err_deregister; usb_set_intfdata(interface, phy); return 0; +err_deregister: + pn533_unregister_device(phy->priv); error: + usb_kill_urb(phy->in_urb); + usb_kill_urb(phy->out_urb); + usb_kill_urb(phy->ack_urb); + usb_free_urb(phy->in_urb); usb_free_urb(phy->out_urb); usb_free_urb(phy->ack_urb); usb_put_dev(phy->udev); kfree(in_buf); + kfree(phy->ack_buffer); return rc; } diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index fd7dea36c3b6832c31aa63ba74b1bb68fa09a376..fa7ba09dca77199708b2729a6747ad9c96c9e84f 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -116,10 +116,26 @@ static void nvme_queue_scan(struct nvme_ctrl *ctrl) /* * Only new queue scan work when admin and IO queues are both alive */ - if (ctrl->state == NVME_CTRL_LIVE) + if (ctrl->state == NVME_CTRL_LIVE && ctrl->tagset) queue_work(nvme_wq, &ctrl->scan_work); } +/* + * Use this function to proceed with scheduling reset_work for a controller + * that had previously been set to the resetting state. This is intended for + * code paths that can't be interrupted by other reset attempts. A hot removal + * may prevent this from succeeding. + */ +int nvme_try_sched_reset(struct nvme_ctrl *ctrl) +{ + if (ctrl->state != NVME_CTRL_RESETTING) + return -EBUSY; + if (!queue_work(nvme_reset_wq, &ctrl->reset_work)) + return -EBUSY; + return 0; +} +EXPORT_SYMBOL_GPL(nvme_try_sched_reset); + int nvme_reset_ctrl(struct nvme_ctrl *ctrl) { if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) @@ -137,8 +153,7 @@ int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl) ret = nvme_reset_ctrl(ctrl); if (!ret) { flush_work(&ctrl->reset_work); - if (ctrl->state != NVME_CTRL_LIVE && - ctrl->state != NVME_CTRL_ADMIN_ONLY) + if (ctrl->state != NVME_CTRL_LIVE) ret = -ENETRESET; } @@ -315,15 +330,6 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, old_state = ctrl->state; switch (new_state) { - case NVME_CTRL_ADMIN_ONLY: - switch (old_state) { - case NVME_CTRL_CONNECTING: - changed = true; - /* FALLTHRU */ - default: - break; - } - break; case NVME_CTRL_LIVE: switch (old_state) { case NVME_CTRL_NEW: @@ -339,7 +345,6 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, switch (old_state) { case NVME_CTRL_NEW: case NVME_CTRL_LIVE: - case NVME_CTRL_ADMIN_ONLY: changed = true; /* FALLTHRU */ default: @@ -359,7 +364,6 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, case NVME_CTRL_DELETING: switch (old_state) { case NVME_CTRL_LIVE: - case NVME_CTRL_ADMIN_ONLY: case NVME_CTRL_RESETTING: case NVME_CTRL_CONNECTING: changed = true; @@ -381,8 +385,10 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, break; } - if (changed) + if (changed) { ctrl->state = new_state; + wake_up_all(&ctrl->state_wq); + } spin_unlock_irqrestore(&ctrl->lock, flags); if (changed && ctrl->state == NVME_CTRL_LIVE) @@ -391,6 +397,39 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, } EXPORT_SYMBOL_GPL(nvme_change_ctrl_state); +/* + * Returns true for sink states that can't ever transition back to live. + */ +static bool nvme_state_terminal(struct nvme_ctrl *ctrl) +{ + switch (ctrl->state) { + case NVME_CTRL_NEW: + case NVME_CTRL_LIVE: + case NVME_CTRL_RESETTING: + case NVME_CTRL_CONNECTING: + return false; + case NVME_CTRL_DELETING: + case NVME_CTRL_DEAD: + return true; + default: + WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state); + return true; + } +} + +/* + * Waits for the controller state to be resetting, or returns false if it is + * not possible to ever transition to that state. + */ +bool nvme_wait_reset(struct nvme_ctrl *ctrl) +{ + wait_event(ctrl->state_wq, + nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING) || + nvme_state_terminal(ctrl)); + return ctrl->state == NVME_CTRL_RESETTING; +} +EXPORT_SYMBOL_GPL(nvme_wait_reset); + static void nvme_free_ns_head(struct kref *ref) { struct nvme_ns_head *head = @@ -1306,8 +1345,6 @@ static void nvme_update_formats(struct nvme_ctrl *ctrl) if (ns->disk && nvme_revalidate_disk(ns->disk)) nvme_set_queue_dying(ns); up_read(&ctrl->namespaces_rwsem); - - nvme_remove_invalid_namespaces(ctrl, NVME_NSID_ALL); } static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects) @@ -1323,6 +1360,7 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects) nvme_unfreeze(ctrl); nvme_mpath_unfreeze(ctrl->subsys); mutex_unlock(&ctrl->subsys->lock); + nvme_remove_invalid_namespaces(ctrl, NVME_NSID_ALL); mutex_unlock(&ctrl->scan_lock); } if (effects & NVME_CMD_EFFECTS_CCC) @@ -2874,7 +2912,6 @@ static int nvme_dev_open(struct inode *inode, struct file *file) switch (ctrl->state) { case NVME_CTRL_LIVE: - case NVME_CTRL_ADMIN_ONLY: break; default: return -EWOULDBLOCK; @@ -3168,7 +3205,6 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, static const char *const state_name[] = { [NVME_CTRL_NEW] = "new", [NVME_CTRL_LIVE] = "live", - [NVME_CTRL_ADMIN_ONLY] = "only-admin", [NVME_CTRL_RESETTING] = "resetting", [NVME_CTRL_CONNECTING] = "connecting", [NVME_CTRL_DELETING] = "deleting", @@ -3679,11 +3715,10 @@ static void nvme_scan_work(struct work_struct *work) struct nvme_id_ctrl *id; unsigned nn; - if (ctrl->state != NVME_CTRL_LIVE) + /* No tagset on a live ctrl means IO queues could not created */ + if (ctrl->state != NVME_CTRL_LIVE || !ctrl->tagset) return; - WARN_ON_ONCE(!ctrl->tagset); - if (test_and_clear_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) { dev_info(ctrl->device, "rescanning namespaces.\n"); nvme_clear_changed_ns_log(ctrl); @@ -3844,13 +3879,13 @@ static void nvme_fw_act_work(struct work_struct *work) if (time_after(jiffies, fw_act_timeout)) { dev_warn(ctrl->device, "Fw activation timeout, reset controller\n"); - nvme_reset_ctrl(ctrl); - break; + nvme_try_sched_reset(ctrl); + return; } msleep(100); } - if (ctrl->state != NVME_CTRL_LIVE) + if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_LIVE)) return; nvme_start_queues(ctrl); @@ -3870,7 +3905,13 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result) nvme_queue_scan(ctrl); break; case NVME_AER_NOTICE_FW_ACT_STARTING: - queue_work(nvme_wq, &ctrl->fw_act_work); + /* + * We are (ab)using the RESETTING state to prevent subsequent + * recovery actions from interfering with the controller's + * firmware activation. + */ + if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) + queue_work(nvme_wq, &ctrl->fw_act_work); break; #ifdef CONFIG_NVME_MULTIPATH case NVME_AER_NOTICE_ANA: @@ -3993,6 +4034,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, INIT_WORK(&ctrl->async_event_work, nvme_async_event_work); INIT_WORK(&ctrl->fw_act_work, nvme_fw_act_work); INIT_WORK(&ctrl->delete_work, nvme_delete_ctrl_work); + init_waitqueue_head(&ctrl->state_wq); INIT_DELAYED_WORK(&ctrl->ka_work, nvme_keep_alive_work); memset(&ctrl->ka_cmd, 0, sizeof(ctrl->ka_cmd)); diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h index 93f08d77c89672d2717dc89a5ff2f314f3ff1fec..a0ec40ab62eeba697575da4bd02fdc9cdfd31409 100644 --- a/drivers/nvme/host/fabrics.h +++ b/drivers/nvme/host/fabrics.h @@ -182,8 +182,7 @@ bool nvmf_ip_options_match(struct nvme_ctrl *ctrl, static inline bool nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq, bool queue_live) { - if (likely(ctrl->state == NVME_CTRL_LIVE || - ctrl->state == NVME_CTRL_ADMIN_ONLY)) + if (likely(ctrl->state == NVME_CTRL_LIVE)) return true; return __nvmf_check_ready(ctrl, rq, queue_live); } diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 30de7efef00357f5231ebdee06953aa341aac6fc..fc99a40c1ec4c0e6a561e5e791a5602393fad475 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -522,14 +522,13 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl, return 0; } -static int nvme_read_ana_log(struct nvme_ctrl *ctrl, bool groups_only) +static int nvme_read_ana_log(struct nvme_ctrl *ctrl) { u32 nr_change_groups = 0; int error; mutex_lock(&ctrl->ana_lock); - error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA, - groups_only ? NVME_ANA_LOG_RGO : 0, + error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA, 0, ctrl->ana_log_buf, ctrl->ana_log_size, 0); if (error) { dev_warn(ctrl->device, "Failed to get ANA log: %d\n", error); @@ -565,7 +564,7 @@ static void nvme_ana_work(struct work_struct *work) { struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, ana_work); - nvme_read_ana_log(ctrl, false); + nvme_read_ana_log(ctrl); } static void nvme_anatt_timeout(struct timer_list *t) @@ -715,7 +714,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) goto out; } - error = nvme_read_ana_log(ctrl, true); + error = nvme_read_ana_log(ctrl); if (error) goto out_free_ana_log_buf; return 0; diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 38a83ef5bcd3513e13b8f00f567ed61efec1f8d6..22e8401352c22b19d397a779006ae0ffaa49f614 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -161,7 +162,6 @@ static inline u16 nvme_req_qid(struct request *req) enum nvme_ctrl_state { NVME_CTRL_NEW, NVME_CTRL_LIVE, - NVME_CTRL_ADMIN_ONLY, /* Only admin queue live */ NVME_CTRL_RESETTING, NVME_CTRL_CONNECTING, NVME_CTRL_DELETING, @@ -199,6 +199,7 @@ struct nvme_ctrl { struct cdev cdev; struct work_struct reset_work; struct work_struct delete_work; + wait_queue_head_t state_wq; struct nvme_subsystem *subsys; struct list_head subsys_entry; @@ -449,6 +450,7 @@ void nvme_complete_rq(struct request *req); bool nvme_cancel_request(struct request *req, void *data, bool reserved); bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, enum nvme_ctrl_state new_state); +bool nvme_wait_reset(struct nvme_ctrl *ctrl); int nvme_disable_ctrl(struct nvme_ctrl *ctrl); int nvme_enable_ctrl(struct nvme_ctrl *ctrl); int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl); @@ -499,6 +501,7 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count); void nvme_stop_keep_alive(struct nvme_ctrl *ctrl); int nvme_reset_ctrl(struct nvme_ctrl *ctrl); int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl); +int nvme_try_sched_reset(struct nvme_ctrl *ctrl); int nvme_delete_ctrl(struct nvme_ctrl *ctrl); int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index bb88681f4dc35c386b47cbd571824f06d7cce2bf..869f462e6b6ea01c5951e94ad247a3f727b215fe 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -773,7 +773,8 @@ static blk_status_t nvme_setup_prp_simple(struct nvme_dev *dev, struct bio_vec *bv) { struct nvme_iod *iod = blk_mq_rq_to_pdu(req); - unsigned int first_prp_len = dev->ctrl.page_size - bv->bv_offset; + unsigned int offset = bv->bv_offset & (dev->ctrl.page_size - 1); + unsigned int first_prp_len = dev->ctrl.page_size - offset; iod->first_dma = dma_map_bvec(dev->dev, bv, rq_dma_dir(req), 0); if (dma_mapping_error(dev->dev, iod->first_dma)) @@ -2263,10 +2264,7 @@ static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode) return true; } -/* - * return error value only when tagset allocation failed - */ -static int nvme_dev_add(struct nvme_dev *dev) +static void nvme_dev_add(struct nvme_dev *dev) { int ret; @@ -2296,7 +2294,7 @@ static int nvme_dev_add(struct nvme_dev *dev) if (ret) { dev_warn(dev->ctrl.device, "IO queues tagset allocation failed %d\n", ret); - return ret; + return; } dev->ctrl.tagset = &dev->tagset; } else { @@ -2307,7 +2305,6 @@ static int nvme_dev_add(struct nvme_dev *dev) } nvme_dbbuf_set(dev); - return 0; } static int nvme_pci_enable(struct nvme_dev *dev) @@ -2467,6 +2464,14 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) mutex_unlock(&dev->shutdown_lock); } +static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown) +{ + if (!nvme_wait_reset(&dev->ctrl)) + return -EBUSY; + nvme_dev_disable(dev, shutdown); + return 0; +} + static int nvme_setup_prp_pools(struct nvme_dev *dev) { dev->prp_page_pool = dma_pool_create("prp list page", dev->dev, @@ -2490,14 +2495,20 @@ static void nvme_release_prp_pools(struct nvme_dev *dev) dma_pool_destroy(dev->prp_small_pool); } +static void nvme_free_tagset(struct nvme_dev *dev) +{ + if (dev->tagset.tags) + blk_mq_free_tag_set(&dev->tagset); + dev->ctrl.tagset = NULL; +} + static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) { struct nvme_dev *dev = to_nvme_dev(ctrl); nvme_dbbuf_dma_free(dev); put_device(dev->dev); - if (dev->tagset.tags) - blk_mq_free_tag_set(&dev->tagset); + nvme_free_tagset(dev); if (dev->ctrl.admin_q) blk_put_queue(dev->ctrl.admin_q); kfree(dev->queues); @@ -2508,6 +2519,11 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) static void nvme_remove_dead_ctrl(struct nvme_dev *dev) { + /* + * Set state to deleting now to avoid blocking nvme_wait_reset(), which + * may be holding this pci_dev's device lock. + */ + nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING); nvme_get_ctrl(&dev->ctrl); nvme_dev_disable(dev, false); nvme_kill_queues(&dev->ctrl); @@ -2521,7 +2537,6 @@ static void nvme_reset_work(struct work_struct *work) container_of(work, struct nvme_dev, ctrl.reset_work); bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL); int result; - enum nvme_ctrl_state new_state = NVME_CTRL_LIVE; if (WARN_ON(dev->ctrl.state != NVME_CTRL_RESETTING)) { result = -ENODEV; @@ -2615,13 +2630,11 @@ static void nvme_reset_work(struct work_struct *work) dev_warn(dev->ctrl.device, "IO queues not created\n"); nvme_kill_queues(&dev->ctrl); nvme_remove_namespaces(&dev->ctrl); - new_state = NVME_CTRL_ADMIN_ONLY; + nvme_free_tagset(dev); } else { nvme_start_queues(&dev->ctrl); nvme_wait_freeze(&dev->ctrl); - /* hit this only when allocate tagset fails */ - if (nvme_dev_add(dev)) - new_state = NVME_CTRL_ADMIN_ONLY; + nvme_dev_add(dev); nvme_unfreeze(&dev->ctrl); } @@ -2629,9 +2642,9 @@ static void nvme_reset_work(struct work_struct *work) * If only admin queue live, keep it to do further investigation or * recovery. */ - if (!nvme_change_ctrl_state(&dev->ctrl, new_state)) { + if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_LIVE)) { dev_warn(dev->ctrl.device, - "failed to mark controller state %d\n", new_state); + "failed to mark controller live state\n"); result = -ENODEV; goto out; } @@ -2672,7 +2685,7 @@ static int nvme_pci_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val) static int nvme_pci_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val) { - *val = readq(to_nvme_dev(ctrl)->bar + off); + *val = lo_hi_readq(to_nvme_dev(ctrl)->bar + off); return 0; } @@ -2836,19 +2849,28 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) static void nvme_reset_prepare(struct pci_dev *pdev) { struct nvme_dev *dev = pci_get_drvdata(pdev); - nvme_dev_disable(dev, false); + + /* + * We don't need to check the return value from waiting for the reset + * state as pci_dev device lock is held, making it impossible to race + * with ->remove(). + */ + nvme_disable_prepare_reset(dev, false); + nvme_sync_queues(&dev->ctrl); } static void nvme_reset_done(struct pci_dev *pdev) { struct nvme_dev *dev = pci_get_drvdata(pdev); - nvme_reset_ctrl_sync(&dev->ctrl); + + if (!nvme_try_sched_reset(&dev->ctrl)) + flush_work(&dev->ctrl.reset_work); } static void nvme_shutdown(struct pci_dev *pdev) { struct nvme_dev *dev = pci_get_drvdata(pdev); - nvme_dev_disable(dev, true); + nvme_disable_prepare_reset(dev, true); } /* @@ -2901,7 +2923,7 @@ static int nvme_resume(struct device *dev) if (ndev->last_ps == U32_MAX || nvme_set_power_state(ctrl, ndev->last_ps) != 0) - nvme_reset_ctrl(ctrl); + return nvme_try_sched_reset(&ndev->ctrl); return 0; } @@ -2929,17 +2951,14 @@ static int nvme_suspend(struct device *dev) */ if (pm_suspend_via_firmware() || !ctrl->npss || !pcie_aspm_enabled(pdev) || - (ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND)) { - nvme_dev_disable(ndev, true); - return 0; - } + (ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND)) + return nvme_disable_prepare_reset(ndev, true); nvme_start_freeze(ctrl); nvme_wait_freeze(ctrl); nvme_sync_queues(ctrl); - if (ctrl->state != NVME_CTRL_LIVE && - ctrl->state != NVME_CTRL_ADMIN_ONLY) + if (ctrl->state != NVME_CTRL_LIVE) goto unfreeze; ret = nvme_get_power_state(ctrl, &ndev->last_ps); @@ -2965,9 +2984,8 @@ static int nvme_suspend(struct device *dev) * Clearing npss forces a controller reset on resume. The * correct value will be resdicovered then. */ - nvme_dev_disable(ndev, true); + ret = nvme_disable_prepare_reset(ndev, true); ctrl->npss = 0; - ret = 0; } unfreeze: nvme_unfreeze(ctrl); @@ -2977,9 +2995,7 @@ static int nvme_suspend(struct device *dev) static int nvme_simple_suspend(struct device *dev) { struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev)); - - nvme_dev_disable(ndev, true); - return 0; + return nvme_disable_prepare_reset(ndev, true); } static int nvme_simple_resume(struct device *dev) @@ -2987,8 +3003,7 @@ static int nvme_simple_resume(struct device *dev) struct pci_dev *pdev = to_pci_dev(dev); struct nvme_dev *ndev = pci_get_drvdata(pdev); - nvme_reset_ctrl(&ndev->ctrl); - return 0; + return nvme_try_sched_reset(&ndev->ctrl); } static const struct dev_pm_ops nvme_dev_pm_ops = { diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 4d280160dd3fd32608b5d4e9a7b699646adcdaf8..f19a28b4e997f473c40c56c0564645565b8c71e7 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -1701,6 +1701,14 @@ nvme_rdma_timeout(struct request *rq, bool reserved) dev_warn(ctrl->ctrl.device, "I/O %d QID %d timeout\n", rq->tag, nvme_rdma_queue_idx(queue)); + /* + * Restart the timer if a controller reset is already scheduled. Any + * timed out commands would be handled before entering the connecting + * state. + */ + if (ctrl->ctrl.state == NVME_CTRL_RESETTING) + return BLK_EH_RESET_TIMER; + if (ctrl->ctrl.state != NVME_CTRL_LIVE) { /* * Teardown immediately if controller times out while starting diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 385a5212c10f199126cd2627a5264ed82b753b76..7544be84ab3582e27ded19298b45960ce3460d96 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1386,7 +1386,9 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, queue->sock->sk->sk_data_ready = nvme_tcp_data_ready; queue->sock->sk->sk_state_change = nvme_tcp_state_change; queue->sock->sk->sk_write_space = nvme_tcp_write_space; +#ifdef CONFIG_NET_RX_BUSY_POLL queue->sock->sk->sk_ll_usec = 1; +#endif write_unlock_bh(&queue->sock->sk->sk_callback_lock); return 0; @@ -2044,6 +2046,14 @@ nvme_tcp_timeout(struct request *rq, bool reserved) struct nvme_tcp_ctrl *ctrl = req->queue->ctrl; struct nvme_tcp_cmd_pdu *pdu = req->pdu; + /* + * Restart the timer if a controller reset is already scheduled. Any + * timed out commands would be handled before entering the connecting + * state. + */ + if (ctrl->ctrl.state == NVME_CTRL_RESETTING) + return BLK_EH_RESET_TIMER; + dev_warn(ctrl->ctrl.device, "queue %d: timeout request %#x type %d\n", nvme_tcp_queue_id(req->queue), rq->tag, pdu->hdr.type); @@ -2126,6 +2136,7 @@ static blk_status_t nvme_tcp_setup_cmd_pdu(struct nvme_ns *ns, ret = nvme_tcp_map_data(queue, rq); if (unlikely(ret)) { + nvme_cleanup_cmd(rq); dev_err(queue->ctrl->ctrl.device, "Failed to map data (%d)\n", ret); return ret; @@ -2208,7 +2219,7 @@ static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx) struct nvme_tcp_queue *queue = hctx->driver_data; struct sock *sk = queue->sock->sk; - if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue)) + if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue)) sk_busy_loop(sk, true); nvme_tcp_try_recv(queue); return queue->nr_cqe; diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c index 748a39fca771408717d18dc1c61e4723d62c6078..11f5aea97d1b1f704d30897d6dc3e2f42d86a0a0 100644 --- a/drivers/nvme/target/loop.c +++ b/drivers/nvme/target/loop.c @@ -157,8 +157,10 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx, iod->sg_table.sgl = iod->first_sgl; if (sg_alloc_table_chained(&iod->sg_table, blk_rq_nr_phys_segments(req), - iod->sg_table.sgl, SG_CHUNK_SIZE)) + iod->sg_table.sgl, SG_CHUNK_SIZE)) { + nvme_cleanup_cmd(req); return BLK_STS_RESOURCE; + } iod->req.sg = iod->sg_table.sgl; iod->req.sg_cnt = blk_rq_map_sg(req->q, req, iod->sg_table.sgl); diff --git a/drivers/of/base.c b/drivers/of/base.c index 1d667eb730e197d7de686a074f6194c1036a64b6..ff896fcc8efa0d0b18264473a57036de8b081796 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1404,6 +1404,7 @@ int of_phandle_iterator_args(struct of_phandle_iterator *it, return count; } +EXPORT_SYMBOL_GPL(of_phandle_iterator_args); static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, diff --git a/drivers/of/property.c b/drivers/of/property.c index 98c5042f352f83291685ee9645d26c29dd9f89c4..0fc89e31e08774f28f5d2afa935a277f5b16850c 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1018,10 +1018,10 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor, * - -EINVAL if the supplier link is invalid and should not be created * - -ENODEV if there is no device that corresponds to the supplier phandle */ -static int of_link_to_phandle(struct device *dev, struct device_node *sup_np) +static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, + u32 dl_flags) { struct device *sup_dev; - u32 dl_flags = DL_FLAG_AUTOPROBE_CONSUMER; int ret = 0; struct device_node *tmp_np = sup_np; @@ -1154,12 +1154,12 @@ struct supplier_bindings { const char *prop_name, int index); }; -static const struct supplier_bindings bindings[] = { +static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_clocks, }, { .parse_prop = parse_interconnects, }, { .parse_prop = parse_regulators, }, { .parse_prop = parse_iommus, }, - {}, + {} }; /** @@ -1185,17 +1185,24 @@ static int of_link_property(struct device *dev, struct device_node *con_np, const char *prop_name) { struct device_node *phandle; - const struct supplier_bindings *s = bindings; + const struct supplier_bindings *s = of_supplier_bindings; unsigned int i = 0; bool matched = false; int ret = 0; + u32 dl_flags; + + if (dev->of_node == con_np) + dl_flags = DL_FLAG_AUTOPROBE_CONSUMER; + else + dl_flags = DL_FLAG_SYNC_STATE_ONLY; /* Do not stop at first failed link, link all available suppliers. */ while (!matched && s->parse_prop) { while ((phandle = s->parse_prop(con_np, prop_name, i))) { matched = true; i++; - if (of_link_to_phandle(dev, phandle) == -EAGAIN) + if (of_link_to_phandle(dev, phandle, dl_flags) + == -EAGAIN) ret = -EAGAIN; of_node_put(phandle); } @@ -1204,7 +1211,7 @@ static int of_link_property(struct device *dev, struct device_node *con_np, return ret; } -static int __of_link_to_suppliers(struct device *dev, +static int of_link_to_suppliers(struct device *dev, struct device_node *con_np) { struct device_node *child; @@ -1213,16 +1220,16 @@ static int __of_link_to_suppliers(struct device *dev, for_each_property_of_node(con_np, p) if (of_link_property(dev, con_np, p->name)) - ret = -EAGAIN; + ret = -ENODEV; for_each_child_of_node(con_np, child) - if (__of_link_to_suppliers(dev, child)) + if (of_link_to_suppliers(dev, child) && !ret) ret = -EAGAIN; return ret; } -static bool of_devlink; +static bool of_devlink = true; core_param(of_devlink, of_devlink, bool, 0); static int of_fwnode_add_links(const struct fwnode_handle *fwnode, @@ -1234,7 +1241,7 @@ static int of_fwnode_add_links(const struct fwnode_handle *fwnode, if (unlikely(!is_of_node(fwnode))) return 0; - return __of_link_to_suppliers(dev, to_of_node(fwnode)); + return of_link_to_suppliers(dev, to_of_node(fwnode)); } const struct fwnode_operations of_fwnode_ops = { diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 480a21e2ed39c738cbd1f66945ccdd3c2e0211b7..92e895d8645844a6a87a453259a5819541becd2c 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1207,6 +1207,7 @@ static int __init unittest_data_add(void) of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); if (!unittest_data_node) { pr_warn("%s: No tree to attach; not running tests\n", __func__); + kfree(unittest_data); return -ENODATA; } diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 3b7ffd0234e9c7c44a1bcbd9b924a1879b9e4207..9ff0538ee83a015d68af4425547a9998656d28eb 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1626,12 +1626,6 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, goto free_regulators; } - ret = regulator_enable(reg); - if (ret < 0) { - regulator_put(reg); - goto free_regulators; - } - opp_table->regulators[i] = reg; } @@ -1645,10 +1639,8 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, return opp_table; free_regulators: - while (i--) { - regulator_disable(opp_table->regulators[i]); - regulator_put(opp_table->regulators[i]); - } + while (i != 0) + regulator_put(opp_table->regulators[--i]); kfree(opp_table->regulators); opp_table->regulators = NULL; @@ -1674,10 +1666,8 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table) /* Make sure there are no concurrent readers while updating opp_table */ WARN_ON(!list_empty(&opp_table->opp_list)); - for (i = opp_table->regulator_count - 1; i >= 0; i--) { - regulator_disable(opp_table->regulators[i]); + for (i = opp_table->regulator_count - 1; i >= 0; i--) regulator_put(opp_table->regulators[i]); - } _free_set_opp_data(opp_table); diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 1813f5ad5fa23b4f4a0f81ef16c7aab159320e96..1cbb58240b8016383d9f1e9137b7190cff345935 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -77,8 +77,6 @@ static struct dev_pm_opp *_find_opp_of_np(struct opp_table *opp_table, { struct dev_pm_opp *opp; - lockdep_assert_held(&opp_table_lock); - mutex_lock(&opp_table->lock); list_for_each_entry(opp, &opp_table->opp_list, node) { @@ -665,6 +663,13 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) return 0; } + /* + * Re-initialize list_kref every time we add static OPPs to the OPP + * table as the reference count may be 0 after the last tie static OPPs + * were removed. + */ + kref_init(&opp_table->list_kref); + /* We have opp-table node now, iterate over it and add OPPs */ for_each_available_child_of_node(opp_table->np, np) { opp = _opp_add_static_v2(opp_table, dev, np); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index ed50502cc65ad29836f5aa47253a0e974ae22471..de8e4e347249179a7cd3085f6a3c6f49e8ffd369 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -678,14 +678,6 @@ static int sba_dma_supported( struct device *dev, u64 mask) return(0); } - /* Documentation/DMA-API-HOWTO.txt tells drivers to try 64-bit - * first, then fall back to 32-bit if that fails. - * We are just "encouraging" 32-bit DMA masks here since we can - * never allow IOMMU bypass unless we add special support for ZX1. - */ - if (mask > ~0U) - return 0; - ioc = GET_IOC(dev); if (!ioc) return 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e7982af9a5d86efd738640fbe08dba01e4704155..3ec31d9d902e04a4e70e9d26b41cf8d54c1a0a09 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -958,19 +958,6 @@ void pci_refresh_power_state(struct pci_dev *dev) pci_update_current_state(dev, dev->current_state); } -/** - * pci_power_up - Put the given device into D0 forcibly - * @dev: PCI device to power up - */ -void pci_power_up(struct pci_dev *dev) -{ - if (platform_pci_power_manageable(dev)) - platform_pci_set_power_state(dev, PCI_D0); - - pci_raw_set_power_state(dev, PCI_D0); - pci_update_current_state(dev, PCI_D0); -} - /** * pci_platform_power_transition - Use platform to change device power state * @dev: PCI device to handle. @@ -1153,6 +1140,17 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) } EXPORT_SYMBOL(pci_set_power_state); +/** + * pci_power_up - Put the given device into D0 forcibly + * @dev: PCI device to power up + */ +void pci_power_up(struct pci_dev *dev) +{ + __pci_start_power_transition(dev, PCI_D0); + pci_raw_set_power_state(dev, PCI_D0); + pci_update_current_state(dev, PCI_D0); +} + /** * pci_choose_state - Choose the power state of a PCI device * @dev: PCI device to be suspended @@ -3173,6 +3171,7 @@ void pci_request_acs(void) { pci_acs_enable = 1; } +EXPORT_SYMBOL_GPL(pci_request_acs); static const char *disable_acs_redir_param; diff --git a/drivers/pci/search.c b/drivers/pci/search.c index bade14002fd8ad9afa5f3910458d4b3fcd9ea924..58b3997a2886a6413f1aa729876ded555977dde1 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -106,6 +106,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev, return ret; } +EXPORT_SYMBOL_GPL(pci_for_each_dma_alias); static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) { diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c index 648ddb7f038a3e866c240c64a1636defeba46c60..c6800d220920ecb3613789ac094d8105ae0cdd94 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c @@ -87,7 +87,7 @@ FUNC_GROUP_DECL(MACLINK3, L23); #define K25 7 SIG_EXPR_LIST_DECL_SESG(K25, MACLINK4, MACLINK4, SIG_DESC_SET(SCU410, 7)); -SIG_EXPR_LIST_DECL_SESG(K25, SDA14, SDA14, SIG_DESC_SET(SCU4B0, 7)); +SIG_EXPR_LIST_DECL_SESG(K25, SDA14, I2C14, SIG_DESC_SET(SCU4B0, 7)); PIN_DECL_2(K25, GPIOA7, MACLINK4, SDA14); FUNC_GROUP_DECL(MACLINK4, K25); @@ -1262,13 +1262,13 @@ GROUP_DECL(SPI1, AB11, AC11, AA11); #define AD11 206 SIG_EXPR_LIST_DECL_SEMG(AD11, SPI1DQ2, QSPI1, SPI1, SIG_DESC_SET(SCU438, 14)); SIG_EXPR_LIST_DECL_SEMG(AD11, TXD13, UART13G1, UART13, - SIG_DESC_SET(SCU438, 14)); + SIG_DESC_CLEAR(SCU4B8, 2), SIG_DESC_SET(SCU4D8, 14)); PIN_DECL_2(AD11, GPIOZ6, SPI1DQ2, TXD13); #define AF10 207 SIG_EXPR_LIST_DECL_SEMG(AF10, SPI1DQ3, QSPI1, SPI1, SIG_DESC_SET(SCU438, 15)); SIG_EXPR_LIST_DECL_SEMG(AF10, RXD13, UART13G1, UART13, - SIG_DESC_SET(SCU438, 15)); + SIG_DESC_CLEAR(SCU4B8, 3), SIG_DESC_SET(SCU4D8, 15)); PIN_DECL_2(AF10, GPIOZ7, SPI1DQ3, RXD13); GROUP_DECL(QSPI1, AB11, AC11, AA11, AD11, AF10); @@ -1440,91 +1440,85 @@ FUNC_GROUP_DECL(RGMII2, D4, C2, C1, D3, E4, F5, D2, E3, D1, F4, E2, E1); FUNC_GROUP_DECL(RMII2, D4, C2, C1, D3, D2, D1, F4, E2, E1); #define AB4 232 -SIG_EXPR_LIST_DECL_SESG(AB4, SD3CLK, SD3, SIG_DESC_SET(SCU400, 24)); -PIN_DECL_1(AB4, GPIO18D0, SD3CLK); +SIG_EXPR_LIST_DECL_SEMG(AB4, EMMCCLK, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 24)); +PIN_DECL_1(AB4, GPIO18D0, EMMCCLK); #define AA4 233 -SIG_EXPR_LIST_DECL_SESG(AA4, SD3CMD, SD3, SIG_DESC_SET(SCU400, 25)); -PIN_DECL_1(AA4, GPIO18D1, SD3CMD); +SIG_EXPR_LIST_DECL_SEMG(AA4, EMMCCMD, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 25)); +PIN_DECL_1(AA4, GPIO18D1, EMMCCMD); #define AC4 234 -SIG_EXPR_LIST_DECL_SESG(AC4, SD3DAT0, SD3, SIG_DESC_SET(SCU400, 26)); -PIN_DECL_1(AC4, GPIO18D2, SD3DAT0); +SIG_EXPR_LIST_DECL_SEMG(AC4, EMMCDAT0, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 26)); +PIN_DECL_1(AC4, GPIO18D2, EMMCDAT0); #define AA5 235 -SIG_EXPR_LIST_DECL_SESG(AA5, SD3DAT1, SD3, SIG_DESC_SET(SCU400, 27)); -PIN_DECL_1(AA5, GPIO18D3, SD3DAT1); +SIG_EXPR_LIST_DECL_SEMG(AA5, EMMCDAT1, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 27)); +PIN_DECL_1(AA5, GPIO18D3, EMMCDAT1); #define Y5 236 -SIG_EXPR_LIST_DECL_SESG(Y5, SD3DAT2, SD3, SIG_DESC_SET(SCU400, 28)); -PIN_DECL_1(Y5, GPIO18D4, SD3DAT2); +SIG_EXPR_LIST_DECL_SEMG(Y5, EMMCDAT2, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 28)); +PIN_DECL_1(Y5, GPIO18D4, EMMCDAT2); #define AB5 237 -SIG_EXPR_LIST_DECL_SESG(AB5, SD3DAT3, SD3, SIG_DESC_SET(SCU400, 29)); -PIN_DECL_1(AB5, GPIO18D5, SD3DAT3); +SIG_EXPR_LIST_DECL_SEMG(AB5, EMMCDAT3, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 29)); +PIN_DECL_1(AB5, GPIO18D5, EMMCDAT3); #define AB6 238 -SIG_EXPR_LIST_DECL_SESG(AB6, SD3CD, SD3, SIG_DESC_SET(SCU400, 30)); -PIN_DECL_1(AB6, GPIO18D6, SD3CD); +SIG_EXPR_LIST_DECL_SEMG(AB6, EMMCCD, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 30)); +PIN_DECL_1(AB6, GPIO18D6, EMMCCD); #define AC5 239 -SIG_EXPR_LIST_DECL_SESG(AC5, SD3WP, SD3, SIG_DESC_SET(SCU400, 31)); -PIN_DECL_1(AC5, GPIO18D7, SD3WP); +SIG_EXPR_LIST_DECL_SEMG(AC5, EMMCWP, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 31)); +PIN_DECL_1(AC5, GPIO18D7, EMMCWP); -FUNC_GROUP_DECL(SD3, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5); +GROUP_DECL(EMMCG1, AB4, AA4, AC4, AB6, AC5); +GROUP_DECL(EMMCG4, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5); #define Y1 240 SIG_EXPR_LIST_DECL_SEMG(Y1, FWSPIDCS, FWSPID, FWSPID, SIG_DESC_SET(SCU500, 3)); SIG_EXPR_LIST_DECL_SESG(Y1, VBCS, VB, SIG_DESC_SET(SCU500, 5)); -SIG_EXPR_LIST_DECL_SESG(Y1, SD3DAT4, SD3DAT4, SIG_DESC_SET(SCU404, 0)); -PIN_DECL_3(Y1, GPIO18E0, FWSPIDCS, VBCS, SD3DAT4); -FUNC_GROUP_DECL(SD3DAT4, Y1); +SIG_EXPR_LIST_DECL_SEMG(Y1, EMMCDAT4, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 0)); +PIN_DECL_3(Y1, GPIO18E0, FWSPIDCS, VBCS, EMMCDAT4); #define Y2 241 SIG_EXPR_LIST_DECL_SEMG(Y2, FWSPIDCK, FWSPID, FWSPID, SIG_DESC_SET(SCU500, 3)); SIG_EXPR_LIST_DECL_SESG(Y2, VBCK, VB, SIG_DESC_SET(SCU500, 5)); -SIG_EXPR_LIST_DECL_SESG(Y2, SD3DAT5, SD3DAT5, SIG_DESC_SET(SCU404, 1)); -PIN_DECL_3(Y2, GPIO18E1, FWSPIDCK, VBCK, SD3DAT5); -FUNC_GROUP_DECL(SD3DAT5, Y2); +SIG_EXPR_LIST_DECL_SEMG(Y2, EMMCDAT5, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 1)); +PIN_DECL_3(Y2, GPIO18E1, FWSPIDCK, VBCK, EMMCDAT5); #define Y3 242 SIG_EXPR_LIST_DECL_SEMG(Y3, FWSPIDMOSI, FWSPID, FWSPID, SIG_DESC_SET(SCU500, 3)); SIG_EXPR_LIST_DECL_SESG(Y3, VBMOSI, VB, SIG_DESC_SET(SCU500, 5)); -SIG_EXPR_LIST_DECL_SESG(Y3, SD3DAT6, SD3DAT6, SIG_DESC_SET(SCU404, 2)); -PIN_DECL_3(Y3, GPIO18E2, FWSPIDMOSI, VBMOSI, SD3DAT6); -FUNC_GROUP_DECL(SD3DAT6, Y3); +SIG_EXPR_LIST_DECL_SEMG(Y3, EMMCDAT6, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 2)); +PIN_DECL_3(Y3, GPIO18E2, FWSPIDMOSI, VBMOSI, EMMCDAT6); #define Y4 243 SIG_EXPR_LIST_DECL_SEMG(Y4, FWSPIDMISO, FWSPID, FWSPID, SIG_DESC_SET(SCU500, 3)); SIG_EXPR_LIST_DECL_SESG(Y4, VBMISO, VB, SIG_DESC_SET(SCU500, 5)); -SIG_EXPR_LIST_DECL_SESG(Y4, SD3DAT7, SD3DAT7, SIG_DESC_SET(SCU404, 3)); -PIN_DECL_3(Y4, GPIO18E3, FWSPIDMISO, VBMISO, SD3DAT7); -FUNC_GROUP_DECL(SD3DAT7, Y4); +SIG_EXPR_LIST_DECL_SEMG(Y4, EMMCDAT7, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 3)); +PIN_DECL_3(Y4, GPIO18E3, FWSPIDMISO, VBMISO, EMMCDAT7); GROUP_DECL(FWSPID, Y1, Y2, Y3, Y4); GROUP_DECL(FWQSPID, Y1, Y2, Y3, Y4, AE12, AF12); +GROUP_DECL(EMMCG8, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5, Y1, Y2, Y3, Y4); FUNC_DECL_2(FWSPID, FWSPID, FWQSPID); FUNC_GROUP_DECL(VB, Y1, Y2, Y3, Y4); - +FUNC_DECL_3(EMMC, EMMCG1, EMMCG4, EMMCG8); /* * FIXME: Confirm bits and priorities are the right way around for the * following 4 pins */ #define AF25 244 -SIG_EXPR_LIST_DECL_SEMG(AF25, I3C3SCL, I3C3, I3C3, SIG_DESC_SET(SCU438, 20), - SIG_DESC_SET(SCU4D8, 20)); -SIG_EXPR_LIST_DECL_SESG(AF25, FSI1CLK, FSI1, SIG_DESC_CLEAR(SCU438, 20), - SIG_DESC_SET(SCU4D8, 20)); +SIG_EXPR_LIST_DECL_SEMG(AF25, I3C3SCL, I3C3, I3C3, SIG_DESC_SET(SCU438, 20)); +SIG_EXPR_LIST_DECL_SESG(AF25, FSI1CLK, FSI1, SIG_DESC_SET(SCU4D8, 20)); PIN_DECL_(AF25, SIG_EXPR_LIST_PTR(AF25, I3C3SCL), SIG_EXPR_LIST_PTR(AF25, FSI1CLK)); #define AE26 245 -SIG_EXPR_LIST_DECL_SEMG(AE26, I3C3SDA, I3C3, I3C3, SIG_DESC_SET(SCU438, 21), - SIG_DESC_SET(SCU4D8, 21)); -SIG_EXPR_LIST_DECL_SESG(AE26, FSI1DATA, FSI1, SIG_DESC_CLEAR(SCU438, 21), - SIG_DESC_SET(SCU4D8, 21)); +SIG_EXPR_LIST_DECL_SEMG(AE26, I3C3SDA, I3C3, I3C3, SIG_DESC_SET(SCU438, 21)); +SIG_EXPR_LIST_DECL_SESG(AE26, FSI1DATA, FSI1, SIG_DESC_SET(SCU4D8, 21)); PIN_DECL_(AE26, SIG_EXPR_LIST_PTR(AE26, I3C3SDA), SIG_EXPR_LIST_PTR(AE26, FSI1DATA)); @@ -1533,18 +1527,14 @@ FUNC_DECL_2(I3C3, HVI3C3, I3C3); FUNC_GROUP_DECL(FSI1, AF25, AE26); #define AE25 246 -SIG_EXPR_LIST_DECL_SEMG(AE25, I3C4SCL, I3C4, I3C4, SIG_DESC_SET(SCU438, 22), - SIG_DESC_SET(SCU4D8, 22)); -SIG_EXPR_LIST_DECL_SESG(AE25, FSI2CLK, FSI2, SIG_DESC_CLEAR(SCU438, 22), - SIG_DESC_SET(SCU4D8, 22)); +SIG_EXPR_LIST_DECL_SEMG(AE25, I3C4SCL, I3C4, I3C4, SIG_DESC_SET(SCU438, 22)); +SIG_EXPR_LIST_DECL_SESG(AE25, FSI2CLK, FSI2, SIG_DESC_SET(SCU4D8, 22)); PIN_DECL_(AE25, SIG_EXPR_LIST_PTR(AE25, I3C4SCL), SIG_EXPR_LIST_PTR(AE25, FSI2CLK)); #define AF24 247 -SIG_EXPR_LIST_DECL_SEMG(AF24, I3C4SDA, I3C4, I3C4, SIG_DESC_SET(SCU438, 23), - SIG_DESC_SET(SCU4D8, 23)); -SIG_EXPR_LIST_DECL_SESG(AF24, FSI2DATA, FSI2, SIG_DESC_CLEAR(SCU438, 23), - SIG_DESC_SET(SCU4D8, 23)); +SIG_EXPR_LIST_DECL_SEMG(AF24, I3C4SDA, I3C4, I3C4, SIG_DESC_SET(SCU438, 23)); +SIG_EXPR_LIST_DECL_SESG(AF24, FSI2DATA, FSI2, SIG_DESC_SET(SCU4D8, 23)); PIN_DECL_(AF24, SIG_EXPR_LIST_PTR(AF24, I3C4SDA), SIG_EXPR_LIST_PTR(AF24, FSI2DATA)); @@ -1574,6 +1564,8 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = { ASPEED_PINCTRL_PIN(A3), ASPEED_PINCTRL_PIN(AA11), ASPEED_PINCTRL_PIN(AA12), + ASPEED_PINCTRL_PIN(AA16), + ASPEED_PINCTRL_PIN(AA17), ASPEED_PINCTRL_PIN(AA23), ASPEED_PINCTRL_PIN(AA24), ASPEED_PINCTRL_PIN(AA25), @@ -1585,6 +1577,8 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = { ASPEED_PINCTRL_PIN(AB11), ASPEED_PINCTRL_PIN(AB12), ASPEED_PINCTRL_PIN(AB15), + ASPEED_PINCTRL_PIN(AB16), + ASPEED_PINCTRL_PIN(AB17), ASPEED_PINCTRL_PIN(AB18), ASPEED_PINCTRL_PIN(AB19), ASPEED_PINCTRL_PIN(AB22), @@ -1602,6 +1596,7 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = { ASPEED_PINCTRL_PIN(AC11), ASPEED_PINCTRL_PIN(AC12), ASPEED_PINCTRL_PIN(AC15), + ASPEED_PINCTRL_PIN(AC16), ASPEED_PINCTRL_PIN(AC17), ASPEED_PINCTRL_PIN(AC18), ASPEED_PINCTRL_PIN(AC19), @@ -1619,6 +1614,7 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = { ASPEED_PINCTRL_PIN(AD12), ASPEED_PINCTRL_PIN(AD14), ASPEED_PINCTRL_PIN(AD15), + ASPEED_PINCTRL_PIN(AD16), ASPEED_PINCTRL_PIN(AD19), ASPEED_PINCTRL_PIN(AD20), ASPEED_PINCTRL_PIN(AD22), @@ -1634,8 +1630,11 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = { ASPEED_PINCTRL_PIN(AE12), ASPEED_PINCTRL_PIN(AE14), ASPEED_PINCTRL_PIN(AE15), + ASPEED_PINCTRL_PIN(AE16), ASPEED_PINCTRL_PIN(AE18), ASPEED_PINCTRL_PIN(AE19), + ASPEED_PINCTRL_PIN(AE25), + ASPEED_PINCTRL_PIN(AE26), ASPEED_PINCTRL_PIN(AE7), ASPEED_PINCTRL_PIN(AE8), ASPEED_PINCTRL_PIN(AF10), @@ -1643,6 +1642,8 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = { ASPEED_PINCTRL_PIN(AF12), ASPEED_PINCTRL_PIN(AF14), ASPEED_PINCTRL_PIN(AF15), + ASPEED_PINCTRL_PIN(AF24), + ASPEED_PINCTRL_PIN(AF25), ASPEED_PINCTRL_PIN(AF7), ASPEED_PINCTRL_PIN(AF8), ASPEED_PINCTRL_PIN(AF9), @@ -1792,17 +1793,6 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = { ASPEED_PINCTRL_PIN(Y3), ASPEED_PINCTRL_PIN(Y4), ASPEED_PINCTRL_PIN(Y5), - ASPEED_PINCTRL_PIN(AB16), - ASPEED_PINCTRL_PIN(AA17), - ASPEED_PINCTRL_PIN(AB17), - ASPEED_PINCTRL_PIN(AE16), - ASPEED_PINCTRL_PIN(AC16), - ASPEED_PINCTRL_PIN(AA16), - ASPEED_PINCTRL_PIN(AD16), - ASPEED_PINCTRL_PIN(AF25), - ASPEED_PINCTRL_PIN(AE26), - ASPEED_PINCTRL_PIN(AE25), - ASPEED_PINCTRL_PIN(AF24), }; static const struct aspeed_pin_group aspeed_g6_groups[] = { @@ -1976,11 +1966,9 @@ static const struct aspeed_pin_group aspeed_g6_groups[] = { ASPEED_PINCTRL_GROUP(SALT9G1), ASPEED_PINCTRL_GROUP(SD1), ASPEED_PINCTRL_GROUP(SD2), - ASPEED_PINCTRL_GROUP(SD3), - ASPEED_PINCTRL_GROUP(SD3DAT4), - ASPEED_PINCTRL_GROUP(SD3DAT5), - ASPEED_PINCTRL_GROUP(SD3DAT6), - ASPEED_PINCTRL_GROUP(SD3DAT7), + ASPEED_PINCTRL_GROUP(EMMCG1), + ASPEED_PINCTRL_GROUP(EMMCG4), + ASPEED_PINCTRL_GROUP(EMMCG8), ASPEED_PINCTRL_GROUP(SGPM1), ASPEED_PINCTRL_GROUP(SGPS1), ASPEED_PINCTRL_GROUP(SIOONCTRL), @@ -2059,6 +2047,7 @@ static const struct aspeed_pin_function aspeed_g6_functions[] = { ASPEED_PINCTRL_FUNC(ADC8), ASPEED_PINCTRL_FUNC(ADC9), ASPEED_PINCTRL_FUNC(BMCINT), + ASPEED_PINCTRL_FUNC(EMMC), ASPEED_PINCTRL_FUNC(ESPI), ASPEED_PINCTRL_FUNC(ESPIALT), ASPEED_PINCTRL_FUNC(FSI1), @@ -2191,11 +2180,6 @@ static const struct aspeed_pin_function aspeed_g6_functions[] = { ASPEED_PINCTRL_FUNC(SALT9), ASPEED_PINCTRL_FUNC(SD1), ASPEED_PINCTRL_FUNC(SD2), - ASPEED_PINCTRL_FUNC(SD3), - ASPEED_PINCTRL_FUNC(SD3DAT4), - ASPEED_PINCTRL_FUNC(SD3DAT5), - ASPEED_PINCTRL_FUNC(SD3DAT6), - ASPEED_PINCTRL_FUNC(SD3DAT7), ASPEED_PINCTRL_FUNC(SGPM1), ASPEED_PINCTRL_FUNC(SGPS1), ASPEED_PINCTRL_FUNC(SIOONCTRL), diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.h b/drivers/pinctrl/aspeed/pinmux-aspeed.h index a2c0d52e4f7b654cb360e91aa7227a8abaa295ac..140c5ce9fbc11a4614627d69b7bbdefb9c469b7e 100644 --- a/drivers/pinctrl/aspeed/pinmux-aspeed.h +++ b/drivers/pinctrl/aspeed/pinmux-aspeed.h @@ -508,7 +508,7 @@ struct aspeed_pin_desc { * @idx: The bit index in the register */ #define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1) -#define SIG_DESC_CLEAR(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 0) +#define SIG_DESC_CLEAR(reg, idx) { ASPEED_IP_SCU, reg, BIT_MASK(idx), 0, 0 } #define SIG_DESC_LIST_SYM(sig, group) sig_descs_ ## sig ## _ ## group #define SIG_DESC_LIST_DECL(sig, group, ...) \ @@ -738,6 +738,7 @@ struct aspeed_pin_desc { static const char *FUNC_SYM(func)[] = { __VA_ARGS__ } #define FUNC_DECL_2(func, one, two) FUNC_DECL_(func, #one, #two) +#define FUNC_DECL_3(func, one, two, three) FUNC_DECL_(func, #one, #two, #three) #define FUNC_GROUP_DECL(func, ...) \ GROUP_DECL(func, __VA_ARGS__); \ diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index 6f7d3a2f2e97d8943302e64089ce21717aebc98c..42f7ab383ad9f4dda27b51e5432bd64833abc6a2 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -1,14 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2014-2017 Broadcom - * - * 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ /* @@ -853,7 +845,7 @@ static int iproc_gpio_probe(struct platform_device *pdev) /* optional GPIO interrupt support */ irq = platform_get_irq(pdev, 0); - if (irq) { + if (irq > 0) { struct irq_chip *irqc; struct gpio_irq_chip *girq; diff --git a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c index 2bf6af7df7d94f0b8e5c09fec4876d7818728673..9fabc451550ead855a0beed670522dcba03d290e 100644 --- a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c @@ -640,8 +640,8 @@ static int ns2_pinmux_enable(struct pinctrl_dev *pctrl_dev, const struct ns2_pin_function *func; const struct ns2_pin_group *grp; - if (grp_select > pinctrl->num_groups || - func_select > pinctrl->num_functions) + if (grp_select >= pinctrl->num_groups || + func_select >= pinctrl->num_functions) return -EINVAL; func = &pinctrl->functions[func_select]; diff --git a/drivers/pinctrl/berlin/pinctrl-as370.c b/drivers/pinctrl/berlin/pinctrl-as370.c index 44f8ccdbeeff0a6677de61b729bacec41a606e89..9dfdc275ee33aef3adee096a67489a4bc71ebb67 100644 --- a/drivers/pinctrl/berlin/pinctrl-as370.c +++ b/drivers/pinctrl/berlin/pinctrl-as370.c @@ -43,7 +43,7 @@ static const struct berlin_desc_group as370_soc_pinctrl_groups[] = { BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO5 */ BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* DO3 */ BERLIN_PINCTRL_FUNCTION(0x2, "pwm"), /* PWM5 */ - BERLIN_PINCTRL_FUNCTION(0x3, "spififib"), /* SPDIFIB */ + BERLIN_PINCTRL_FUNCTION(0x3, "spdifib"), /* SPDIFIB */ BERLIN_PINCTRL_FUNCTION(0x4, "spdifo"), /* SPDIFO */ BERLIN_PINCTRL_FUNCTION(0x5, "phy")), /* DBG5 */ BERLIN_PINCTRL_GROUP("I2S1_MCLK", 0x0, 0x3, 0x12, diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index aae51c507f590e77c854a3547779995ea227e7e4..c6251eac8946c339af412763887b1ef93d537555 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1513,7 +1513,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"), - DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, { @@ -1521,7 +1520,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"), - DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, { @@ -1529,7 +1527,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"), - DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, { @@ -1537,7 +1534,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_NAME, "Celes"), - DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), }, }, {} diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 1f13bcd0e4e1447a63cea190dfca301929ea38af..bc013599a9a3840359d024e97281da069f69349a 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -96,6 +96,7 @@ struct intel_pinctrl_context { * @pctldesc: Pin controller description * @pctldev: Pointer to the pin controller device * @chip: GPIO chip in this pin controller + * @irqchip: IRQ chip in this pin controller * @soc: SoC/PCH specific pin configuration data * @communities: All communities in this pin controller * @ncommunities: Number of communities in this pin controller @@ -108,6 +109,7 @@ struct intel_pinctrl { struct pinctrl_desc pctldesc; struct pinctrl_dev *pctldev; struct gpio_chip chip; + struct irq_chip irqchip; const struct intel_pinctrl_soc_data *soc; struct intel_community *communities; size_t ncommunities; @@ -1139,16 +1141,6 @@ static irqreturn_t intel_gpio_irq(int irq, void *data) return ret; } -static struct irq_chip intel_gpio_irqchip = { - .name = "intel-gpio", - .irq_ack = intel_gpio_irq_ack, - .irq_mask = intel_gpio_irq_mask, - .irq_unmask = intel_gpio_irq_unmask, - .irq_set_type = intel_gpio_irq_type, - .irq_set_wake = intel_gpio_irq_wake, - .flags = IRQCHIP_MASK_ON_SUSPEND, -}; - static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl, const struct intel_community *community) { @@ -1198,12 +1190,22 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) pctrl->chip = intel_gpio_chip; + /* Setup GPIO chip */ pctrl->chip.ngpio = intel_gpio_ngpio(pctrl); pctrl->chip.label = dev_name(pctrl->dev); pctrl->chip.parent = pctrl->dev; pctrl->chip.base = -1; pctrl->irq = irq; + /* Setup IRQ chip */ + pctrl->irqchip.name = dev_name(pctrl->dev); + pctrl->irqchip.irq_ack = intel_gpio_irq_ack; + pctrl->irqchip.irq_mask = intel_gpio_irq_mask; + pctrl->irqchip.irq_unmask = intel_gpio_irq_unmask; + pctrl->irqchip.irq_set_type = intel_gpio_irq_type; + pctrl->irqchip.irq_set_wake = intel_gpio_irq_wake; + pctrl->irqchip.flags = IRQCHIP_MASK_ON_SUSPEND; + ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); if (ret) { dev_err(pctrl->dev, "failed to register gpiochip\n"); @@ -1233,15 +1235,14 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) return ret; } - ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0, + ret = gpiochip_irqchip_add(&pctrl->chip, &pctrl->irqchip, 0, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(pctrl->dev, "failed to add irqchip\n"); return ret; } - gpiochip_set_chained_irqchip(&pctrl->chip, &intel_gpio_irqchip, irq, - NULL); + gpiochip_set_chained_irqchip(&pctrl->chip, &pctrl->irqchip, irq, NULL); return 0; } diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 6462d3ca7ceb9b44b406015397102eadec5c2f99..f2f5fcd9a2374f1f1c8a403724503050fad5dc75 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -183,10 +183,10 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = { PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19), BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19), 18, 2, "gpio", "uart"), - PIN_GRP_GPIO("led0_od", 11, 1, BIT(20), "led"), - PIN_GRP_GPIO("led1_od", 12, 1, BIT(21), "led"), - PIN_GRP_GPIO("led2_od", 13, 1, BIT(22), "led"), - PIN_GRP_GPIO("led3_od", 14, 1, BIT(23), "led"), + PIN_GRP_GPIO_2("led0_od", 11, 1, BIT(20), BIT(20), 0, "led"), + PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"), + PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"), + PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"), }; @@ -221,11 +221,11 @@ static const struct armada_37xx_pin_data armada_37xx_pin_sb = { }; static inline void armada_37xx_update_reg(unsigned int *reg, - unsigned int offset) + unsigned int *offset) { /* We never have more than 2 registers */ - if (offset >= GPIO_PER_REG) { - offset -= GPIO_PER_REG; + if (*offset >= GPIO_PER_REG) { + *offset -= GPIO_PER_REG; *reg += sizeof(u32); } } @@ -376,7 +376,7 @@ static inline void armada_37xx_irq_update_reg(unsigned int *reg, { int offset = irqd_to_hwirq(d); - armada_37xx_update_reg(reg, offset); + armada_37xx_update_reg(reg, &offset); } static int armada_37xx_gpio_direction_input(struct gpio_chip *chip, @@ -386,7 +386,7 @@ static int armada_37xx_gpio_direction_input(struct gpio_chip *chip, unsigned int reg = OUTPUT_EN; unsigned int mask; - armada_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, &offset); mask = BIT(offset); return regmap_update_bits(info->regmap, reg, mask, 0); @@ -399,7 +399,7 @@ static int armada_37xx_gpio_get_direction(struct gpio_chip *chip, unsigned int reg = OUTPUT_EN; unsigned int val, mask; - armada_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, &offset); mask = BIT(offset); regmap_read(info->regmap, reg, &val); @@ -413,7 +413,7 @@ static int armada_37xx_gpio_direction_output(struct gpio_chip *chip, unsigned int reg = OUTPUT_EN; unsigned int mask, val, ret; - armada_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, &offset); mask = BIT(offset); ret = regmap_update_bits(info->regmap, reg, mask, mask); @@ -434,7 +434,7 @@ static int armada_37xx_gpio_get(struct gpio_chip *chip, unsigned int offset) unsigned int reg = INPUT_VAL; unsigned int val, mask; - armada_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, &offset); mask = BIT(offset); regmap_read(info->regmap, reg, &val); @@ -449,7 +449,7 @@ static void armada_37xx_gpio_set(struct gpio_chip *chip, unsigned int offset, unsigned int reg = OUTPUT_VAL; unsigned int mask, val; - armada_37xx_update_reg(®, offset); + armada_37xx_update_reg(®, &offset); mask = BIT(offset); val = value ? mask : 0; diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 974973777395d13ef1409d2d721c84ec1fac99ba..564660028fcca66fab080d10033fab43bfb151b0 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -705,7 +705,7 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) static int stmfx_pinctrl_remove(struct platform_device *pdev) { - struct stmfx *stmfx = dev_get_platdata(&pdev->dev); + struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent); return stmfx_function_disable(stmfx, STMFX_FUNC_GPIO | diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index b52e123073c7fac3e39fec013c8b8baaac4584dc..08d53266348d1f3383e24dac07532a5c23513826 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -26,6 +26,8 @@ #include +#include + #include "../core.h" #include "../pinconf.h" #include "pinctrl-msm.h" @@ -1153,6 +1155,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) girq = &chip->irq; girq->chip = &pctrl->irq_chip; girq->parent_handler = msm_gpio_irq_handler; + girq->fwnode = pctrl->dev->fwnode; girq->num_parents = 1; girq->fwnode = pctrl->dev->fwnode; girq->parents = devm_kcalloc(pctrl->dev, 1, sizeof(*girq->parents), diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h index 9f556b685ecbcb3e1367a3f76296d80f4f5028b6..1ae9abcf99a58c569923c004757435cee72d4b26 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.h +++ b/drivers/pinctrl/qcom/pinctrl-msm.h @@ -146,10 +146,10 @@ struct msm_pinctrl_soc_data { const char *const *tiles; unsigned int ntiles; const int *reserved_gpios; - struct pinctrl_qup *qup_regs; - unsigned int nqup_regs; const struct msm_gpio_wakeirq_map *wakeirq_map; unsigned int nwakeirq_map; + struct pinctrl_qup *qup_regs; + unsigned int nqup_regs; }; extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops; diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 86cc2cc68fb51b48d6f1308ff1dfff736e4eb2a5..af063f6908460f240e7221cd3076bd00815441a0 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -420,12 +420,6 @@ static int cmpc_accel_add_v4(struct acpi_device *acpi) static int cmpc_accel_remove_v4(struct acpi_device *acpi) { - struct input_dev *inputdev; - struct cmpc_accel *accel; - - inputdev = dev_get_drvdata(&acpi->dev); - accel = dev_get_drvdata(&inputdev->dev); - device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); return cmpc_remove_acpi_notify_device(acpi); @@ -656,12 +650,6 @@ static int cmpc_accel_add(struct acpi_device *acpi) static int cmpc_accel_remove(struct acpi_device *acpi) { - struct input_dev *inputdev; - struct cmpc_accel *accel; - - inputdev = dev_get_drvdata(&acpi->dev); - accel = dev_get_drvdata(&inputdev->dev); - device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr); return cmpc_remove_acpi_notify_device(acpi); } diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index ea68f6ed66ae396df2002a258493aa3eb31212e6..ffb8d5d1eb5ffe3b661250b4edc6bb0c37a68119 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -108,6 +108,7 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) if (ret < 0) { dev_dbg(dev, "Error requesting irq at index %d: %d\n", inst_data[i].irq_idx, ret); + goto error; } board_info.irq = ret; break; diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c index ab7ae19508676d60387e17c191b79ce3e1e34034..fa97834fdb78e54131a12abd856f92831027e64a 100644 --- a/drivers/platform/x86/intel_punit_ipc.c +++ b/drivers/platform/x86/intel_punit_ipc.c @@ -293,9 +293,8 @@ static int intel_punit_ipc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, punit_ipcdev); - irq = platform_get_irq(pdev, 0); + irq = platform_get_irq_optional(pdev, 0); if (irq < 0) { - punit_ipcdev->irq = 0; dev_warn(&pdev->dev, "Invalid IRQ, using polling mode\n"); } else { ret = devm_request_irq(&pdev->dev, irq, intel_punit_ioc, diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index 960961fb0d7c5c1b3bf91008bd2eae817a72787f..0517272a268edb82743993d49861e17a1fb30f79 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -97,8 +97,8 @@ config PTP_1588_CLOCK_PCH help This driver adds support for using the PCH EG20T as a PTP clock. The hardware supports time stamping of PTP packets - when using the end-to-end delay (E2E) mechansim. The peer - delay mechansim (P2P) is not supported. + when using the end-to-end delay (E2E) mechanism. The peer + delay mechanism (P2P) is not supported. This clock is only useful if your PTP programs are getting hardware time stamps on the PTP Ethernet packets using the diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 6ad51aa60c03dd1cf8afd00410a53a459f4d0a35..f877e77d9184be47710178e11ba8d30bf8522259 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -472,14 +472,7 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) if (err) return err; - /* - * .apply might have to round some values in *state, if possible - * read the actually implemented value back. - */ - if (chip->ops->get_state) - chip->ops->get_state(chip, pwm, &pwm->state); - else - pwm->state = *state; + pwm->state = *state; } else { /* * FIXME: restore the initial state in case of error. diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6e280f32463d5e573de8798e25002e723673b7a7..6149c5fc34940d365613c5e56f4ce4f058da7d22 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5464,6 +5464,19 @@ regulator_register(const struct regulator_desc *regulator_desc, init_data = regulator_of_get_init_data(dev, regulator_desc, config, &rdev->dev.of_node); + + /* + * Sometimes not all resources are probed already so we need to take + * that into account. This happens most the time if the ena_gpiod comes + * from a gpio extender or something else. + */ + if (PTR_ERR(init_data) == -EPROBE_DEFER) { + kfree(config); + kfree(rdev); + ret = -EPROBE_DEFER; + goto rinse; + } + /* * We need to keep track of any GPIO descriptor coming from the * device tree until we have handled it over to the core. If the diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index 56f3f72d77075e01e61beb9592acbbc221750fd7..710e67081d531e630d972feadfd08b177b6748bd 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -136,7 +136,6 @@ static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode) static unsigned da9062_buck_get_mode(struct regulator_dev *rdev) { struct da9062_regulator *regl = rdev_get_drvdata(rdev); - struct regmap_field *field; unsigned int val, mode = 0; int ret; @@ -158,18 +157,7 @@ static unsigned da9062_buck_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; } - /* Detect current regulator state */ - ret = regmap_field_read(regl->suspend, &val); - if (ret < 0) - return 0; - - /* Read regulator mode from proper register, depending on state */ - if (val) - field = regl->suspend_sleep; - else - field = regl->sleep; - - ret = regmap_field_read(field, &val); + ret = regmap_field_read(regl->sleep, &val); if (ret < 0) return 0; @@ -208,21 +196,9 @@ static int da9062_ldo_set_mode(struct regulator_dev *rdev, unsigned mode) static unsigned da9062_ldo_get_mode(struct regulator_dev *rdev) { struct da9062_regulator *regl = rdev_get_drvdata(rdev); - struct regmap_field *field; int ret, val; - /* Detect current regulator state */ - ret = regmap_field_read(regl->suspend, &val); - if (ret < 0) - return 0; - - /* Read regulator mode from proper register, depending on state */ - if (val) - field = regl->suspend_sleep; - else - field = regl->sleep; - - ret = regmap_field_read(field, &val); + ret = regmap_field_read(regl->sleep, &val); if (ret < 0) return 0; @@ -408,10 +384,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { __builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1, sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1), - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_BUCK1_CONT, + __builtin_ffs((int)DA9062AA_BUCK1_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_BUCK1_CONF_MASK) - 1), }, { .desc.id = DA9061_ID_BUCK2, @@ -444,10 +420,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { __builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1, sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1), - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_BUCK3_CONT, + __builtin_ffs((int)DA9062AA_BUCK3_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_BUCK3_CONF_MASK) - 1), }, { .desc.id = DA9061_ID_BUCK3, @@ -480,10 +456,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { __builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1, sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1), - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_BUCK4_CONT, + __builtin_ffs((int)DA9062AA_BUCK4_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_BUCK4_CONF_MASK) - 1), }, { .desc.id = DA9061_ID_LDO1, @@ -509,10 +485,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO1_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO1_CONT, + __builtin_ffs((int)DA9062AA_LDO1_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO1_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - @@ -542,10 +518,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO2_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO2_CONT, + __builtin_ffs((int)DA9062AA_LDO2_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO2_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - @@ -575,10 +551,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO3_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO3_CONT, + __builtin_ffs((int)DA9062AA_LDO3_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO3_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - @@ -608,10 +584,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO4_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO4_CONT, + __builtin_ffs((int)DA9062AA_LDO4_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO4_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - @@ -652,10 +628,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { __builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1, sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1), - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_BUCK1_CONT, + __builtin_ffs((int)DA9062AA_BUCK1_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_BUCK1_CONF_MASK) - 1), }, { .desc.id = DA9062_ID_BUCK2, @@ -688,10 +664,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { __builtin_ffs((int)DA9062AA_BUCK2_MODE_MASK) - 1, sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_BUCK2_MODE_MASK)) - 1), - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VBUCK2_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_BUCK2_CONT, + __builtin_ffs((int)DA9062AA_BUCK2_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VBUCK2_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_BUCK2_CONF_MASK) - 1), }, { .desc.id = DA9062_ID_BUCK3, @@ -724,10 +700,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { __builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1, sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1), - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_BUCK3_CONT, + __builtin_ffs((int)DA9062AA_BUCK3_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_BUCK3_CONF_MASK) - 1), }, { .desc.id = DA9062_ID_BUCK4, @@ -760,10 +736,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { __builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1, sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1), - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_BUCK4_CONT, + __builtin_ffs((int)DA9062AA_BUCK4_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_BUCK4_CONF_MASK) - 1), }, { .desc.id = DA9062_ID_LDO1, @@ -789,10 +765,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO1_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO1_CONT, + __builtin_ffs((int)DA9062AA_LDO1_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO1_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - @@ -822,10 +798,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO2_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO2_CONT, + __builtin_ffs((int)DA9062AA_LDO2_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO2_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - @@ -855,10 +831,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO3_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO3_CONT, + __builtin_ffs((int)DA9062AA_LDO3_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO3_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - @@ -888,10 +864,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { sizeof(unsigned int) * 8 - __builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1), .suspend_vsel_reg = DA9062AA_VLDO4_B, - .suspend = REG_FIELD(DA9062AA_DVC_1, - __builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1, + .suspend = REG_FIELD(DA9062AA_LDO4_CONT, + __builtin_ffs((int)DA9062AA_LDO4_CONF_MASK) - 1, sizeof(unsigned int) * 8 - - __builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1), + __builtin_clz(DA9062AA_LDO4_CONF_MASK) - 1), .oc_event = REG_FIELD(DA9062AA_STATUS_D, __builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1, sizeof(unsigned int) * 8 - diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index d90a6fd8cbc7468f67324322443254388eff2d17..f81533070058e29db66991311ec4bbbec0c32636 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -144,8 +144,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct fixed_voltage_config *config; struct fixed_voltage_data *drvdata; - const struct fixed_dev_type *drvtype = - of_match_device(dev->driver->of_match_table, dev)->data; + const struct fixed_dev_type *drvtype = of_device_get_match_data(dev); struct regulator_config cfg = { }; enum gpiod_flags gflags; int ret; @@ -177,7 +176,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.type = REGULATOR_VOLTAGE; drvdata->desc.owner = THIS_MODULE; - if (drvtype->has_enable_clock) { + if (drvtype && drvtype->has_enable_clock) { drvdata->desc.ops = &fixed_voltage_clkenabled_ops; drvdata->enable_clock = devm_clk_get(dev, NULL); diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c index ff97cc50f2eb96161a44626062e318477d0187dc..9b05e03ba83056d7beedfb4199eed2febb2b1542 100644 --- a/drivers/regulator/lochnagar-regulator.c +++ b/drivers/regulator/lochnagar-regulator.c @@ -210,6 +210,7 @@ static const struct regulator_desc lochnagar_regulators[] = { .enable_time = 3000, .ramp_delay = 1000, + .off_on_delay = 15000, .owner = THIS_MODULE, }, diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index afefb29ce1b0decf8f7ab2105be70ee9f5d59b7a..87637eb6bcbcb9ce2e50278f21bb5dfae315d004 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -231,12 +231,12 @@ static int of_get_regulation_constraints(struct device *dev, "regulator-off-in-suspend")) suspend_state->enabled = DISABLE_IN_SUSPEND; - if (!of_property_read_u32(np, "regulator-suspend-min-microvolt", - &pval)) + if (!of_property_read_u32(suspend_np, + "regulator-suspend-min-microvolt", &pval)) suspend_state->min_uV = pval; - if (!of_property_read_u32(np, "regulator-suspend-max-microvolt", - &pval)) + if (!of_property_read_u32(suspend_np, + "regulator-suspend-max-microvolt", &pval)) suspend_state->max_uV = pval; if (!of_property_read_u32(suspend_np, @@ -445,11 +445,20 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, goto error; } - if (desc->of_parse_cb && desc->of_parse_cb(child, desc, config)) { - dev_err(dev, - "driver callback failed to parse DT for regulator %pOFn\n", - child); - goto error; + if (desc->of_parse_cb) { + int ret; + + ret = desc->of_parse_cb(child, desc, config); + if (ret) { + if (ret == -EPROBE_DEFER) { + of_node_put(child); + return ERR_PTR(-EPROBE_DEFER); + } + dev_err(dev, + "driver callback failed to parse DT for regulator %pOFn\n", + child); + goto error; + } } *node = child; diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index df5df1c495adb861322e356d59c091bbf94b342f..689537927f6f7d1bf4543d246490460971913117 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -788,7 +788,13 @@ static int pfuze100_regulator_probe(struct i2c_client *client, /* SW2~SW4 high bit check and modify the voltage value table */ if (i >= sw_check_start && i <= sw_check_end) { - regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val); + ret = regmap_read(pfuze_chip->regmap, + desc->vsel_reg, &val); + if (ret) { + dev_err(&client->dev, "Fails to read from the register.\n"); + return ret; + } + if (val & sw_hi) { if (pfuze_chip->chip_id == PFUZE3000 || pfuze_chip->chip_id == PFUZE3001) { diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index db6c085da65ecf742daeca83824072ab70a3834b..0246b6f99fb50c4232449def2c005b615e31138d 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -735,8 +735,8 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { static const struct rpmh_vreg_hw_data pmic5_bob = { .regulator_type = VRM, .ops = &rpmh_regulator_vrm_bypass_ops, - .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000), - .n_voltages = 136, + .voltage_range = REGULATOR_LINEAR_RANGE(3000000, 0, 31, 32000), + .n_voltages = 32, .pmic_mode_map = pmic_mode_map_pmic5_bob, .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, }; diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index cced1ffb896c1169dba81bde5c9b83a63890ceab..89b9314d64c9dbe5fe152b06c252b1567600857c 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -173,19 +173,14 @@ static int ti_abb_wait_txdone(struct device *dev, struct ti_abb *abb) while (timeout++ <= abb->settling_time) { status = ti_abb_check_txdone(abb); if (status) - break; + return 0; udelay(1); } - if (timeout > abb->settling_time) { - dev_warn_ratelimited(dev, - "%s:TRANXDONE timeout(%duS) int=0x%08x\n", - __func__, timeout, readl(abb->int_base)); - return -ETIMEDOUT; - } - - return 0; + dev_warn_ratelimited(dev, "%s:TRANXDONE timeout(%duS) int=0x%08x\n", + __func__, timeout, readl(abb->int_base)); + return -ETIMEDOUT; } /** @@ -205,19 +200,14 @@ static int ti_abb_clear_all_txdone(struct device *dev, const struct ti_abb *abb) status = ti_abb_check_txdone(abb); if (!status) - break; + return 0; udelay(1); } - if (timeout > abb->settling_time) { - dev_warn_ratelimited(dev, - "%s:TRANXDONE timeout(%duS) int=0x%08x\n", - __func__, timeout, readl(abb->int_base)); - return -ETIMEDOUT; - } - - return 0; + dev_warn_ratelimited(dev, "%s:TRANXDONE timeout(%duS) int=0x%08x\n", + __func__, timeout, readl(abb->int_base)); + return -ETIMEDOUT; } /** diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 45bdb47f84c10b69572c77cbfa1b1f9ca16b1b5a..9157e728a362dbd5589e2fe786fbd585b5f3f8f5 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -522,8 +522,7 @@ static int zcrypt_release(struct inode *inode, struct file *filp) if (filp->f_inode->i_cdev == &zcrypt_cdev) { struct zcdn_device *zcdndev; - if (mutex_lock_interruptible(&ap_perms_mutex)) - return -ERESTARTSYS; + mutex_lock(&ap_perms_mutex); zcdndev = find_zcdndev_by_devt(filp->f_inode->i_rdev); mutex_unlock(&ap_perms_mutex); if (zcdndev) { diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index b8799cd3e7aaa83196416b64a8343d019fac4642..bd8143e51747a785070c347b68f5d9314d2846f3 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -2021,10 +2021,10 @@ static bool qeth_l2_vnicc_recover_char(struct qeth_card *card, u32 vnicc, static void qeth_l2_vnicc_init(struct qeth_card *card) { u32 *timeout = &card->options.vnicc.learning_timeout; + bool enable, error = false; unsigned int chars_len, i; unsigned long chars_tmp; u32 sup_cmds, vnicc; - bool enable, error; QETH_CARD_TEXT(card, 2, "vniccini"); /* reset rx_bcast */ @@ -2045,17 +2045,24 @@ static void qeth_l2_vnicc_init(struct qeth_card *card) chars_len = sizeof(card->options.vnicc.sup_chars) * BITS_PER_BYTE; for_each_set_bit(i, &chars_tmp, chars_len) { vnicc = BIT(i); - qeth_l2_vnicc_query_cmds(card, vnicc, &sup_cmds); - if (!(sup_cmds & IPA_VNICC_SET_TIMEOUT) || - !(sup_cmds & IPA_VNICC_GET_TIMEOUT)) + if (qeth_l2_vnicc_query_cmds(card, vnicc, &sup_cmds)) { + sup_cmds = 0; + error = true; + } + if ((sup_cmds & IPA_VNICC_SET_TIMEOUT) && + (sup_cmds & IPA_VNICC_GET_TIMEOUT)) + card->options.vnicc.getset_timeout_sup |= vnicc; + else card->options.vnicc.getset_timeout_sup &= ~vnicc; - if (!(sup_cmds & IPA_VNICC_ENABLE) || - !(sup_cmds & IPA_VNICC_DISABLE)) + if ((sup_cmds & IPA_VNICC_ENABLE) && + (sup_cmds & IPA_VNICC_DISABLE)) + card->options.vnicc.set_char_sup |= vnicc; + else card->options.vnicc.set_char_sup &= ~vnicc; } /* enforce assumed default values and recover settings, if changed */ - error = qeth_l2_vnicc_recover_timeout(card, QETH_VNICC_LEARNING, - timeout); + error |= qeth_l2_vnicc_recover_timeout(card, QETH_VNICC_LEARNING, + timeout); chars_tmp = card->options.vnicc.wanted_chars ^ QETH_VNICC_DEFAULT; chars_tmp |= QETH_VNICC_BRIDGE_INVISIBLE; chars_len = sizeof(card->options.vnicc.wanted_chars) * BITS_PER_BYTE; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 296bbc3c4606c178f7b1192edd99e70b9998acc2..cf63916814cca34305b1f28720161633581bb730 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -27,6 +27,11 @@ struct kmem_cache *zfcp_fsf_qtcb_cache; +static bool ber_stop = true; +module_param(ber_stop, bool, 0600); +MODULE_PARM_DESC(ber_stop, + "Shuts down FCP devices for FCP channels that report a bit-error count in excess of its threshold (default on)"); + static void zfcp_fsf_request_timeout_handler(struct timer_list *t) { struct zfcp_fsf_req *fsf_req = from_timer(fsf_req, t, timer); @@ -236,10 +241,15 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) case FSF_STATUS_READ_SENSE_DATA_AVAIL: break; case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: - dev_warn(&adapter->ccw_device->dev, - "The error threshold for checksum statistics " - "has been exceeded\n"); zfcp_dbf_hba_bit_err("fssrh_3", req); + if (ber_stop) { + dev_warn(&adapter->ccw_device->dev, + "All paths over this FCP device are disused because of excessive bit errors\n"); + zfcp_erp_adapter_shutdown(adapter, 0, "fssrh_b"); + } else { + dev_warn(&adapter->ccw_device->dev, + "The error threshold for checksum statistics has been exceeded\n"); + } break; case FSF_STATUS_READ_LINK_DOWN: zfcp_fsf_status_read_link_down(req); diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 1b92f3c19ff32f84403f05cead17ae6a0423608f..90cf4691b8c3592c3f7d6dcda993b96da639ca81 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -898,7 +898,7 @@ config SCSI_SNI_53C710 config 53C700_LE_ON_BE bool - depends on SCSI_LASI700 + depends on SCSI_LASI700 || SCSI_SNI_53C710 default y config SCSI_STEX diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 5f8153c37f77f3393edd428e3c4d2b901040887b..76751d6c7f0d4f13e1347e9562ca63c4e34484d1 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -579,7 +579,6 @@ ch_release(struct inode *inode, struct file *file) scsi_changer *ch = file->private_data; scsi_device_put(ch->device); - ch->device = NULL; file->private_data = NULL; kref_put(&ch->ref, ch_destroy); return 0; diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 4971104b1817b5acc42fcd03e040ced92f63c179..f32da0ca529e004f448c6f9803b9c57b145a6609 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -512,6 +512,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) unsigned int tpg_desc_tbl_off; unsigned char orig_transition_tmo; unsigned long flags; + bool transitioning_sense = false; if (!pg->expiry) { unsigned long transition_tmo = ALUA_FAILOVER_TIMEOUT * HZ; @@ -572,13 +573,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) goto retry; } /* - * Retry on ALUA state transition or if any - * UNIT ATTENTION occurred. + * If the array returns with 'ALUA state transition' + * sense code here it cannot return RTPG data during + * transition. So set the state to 'transitioning' directly. */ if (sense_hdr.sense_key == NOT_READY && - sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) - err = SCSI_DH_RETRY; - else if (sense_hdr.sense_key == UNIT_ATTENTION) + sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) { + transitioning_sense = true; + goto skip_rtpg; + } + /* + * Retry on any other UNIT ATTENTION occurred. + */ + if (sense_hdr.sense_key == UNIT_ATTENTION) err = SCSI_DH_RETRY; if (err == SCSI_DH_RETRY && pg->expiry != 0 && time_before(jiffies, pg->expiry)) { @@ -666,7 +673,11 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) off = 8 + (desc[7] * 4); } + skip_rtpg: spin_lock_irqsave(&pg->lock, flags); + if (transitioning_sense) + pg->state = SCSI_ACCESS_STATE_TRANSITIONING; + sdev_printk(KERN_INFO, sdev, "%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n", ALUA_DH_NAME, pg->group_id, print_alua_state(pg->state), diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ac39ed79ccaa15cebf9a3b7d86230130f4d5b076..216e557f703e6c0b466fc29dddc05364b3127bf2 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -5477,6 +5477,8 @@ static int hpsa_ciss_submit(struct ctlr_info *h, return SCSI_MLQUEUE_HOST_BUSY; } + c->device = dev; + enqueue_cmd_and_start_io(h, c); /* the cmd'll come back via intr handler in complete_scsi_command() */ return 0; @@ -5548,6 +5550,7 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h, hpsa_cmd_init(h, c->cmdindex, c); c->cmd_type = CMD_SCSI; c->scsi_cmd = cmd; + c->device = dev; rc = hpsa_scsi_ioaccel_raid_map(h, c); if (rc < 0) /* scsi_dma_map failed. */ rc = SCSI_MLQUEUE_HOST_BUSY; @@ -5555,6 +5558,7 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h, hpsa_cmd_init(h, c->cmdindex, c); c->cmd_type = CMD_SCSI; c->scsi_cmd = cmd; + c->device = dev; rc = hpsa_scsi_ioaccel_direct_map(h, c); if (rc < 0) /* scsi_dma_map failed. */ rc = SCSI_MLQUEUE_HOST_BUSY; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index e91377a4cafebad115a84465f02ebd59bc5140db..e8813d26e59415b1a584900c2ed7772438a74bc3 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -9055,7 +9055,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) } } -#if defined(BUILD_NVME) /* Clear NVME stats */ if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) { for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { @@ -9063,7 +9062,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba) sizeof(phba->sli4_hba.hdwq[idx].nvme_cstat)); } } -#endif /* Clear SCSI stats */ if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) { diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index f4b879d25fe9d33229d40a5ab5675577b539c45a..fc6e4546d738a59ab1be40271f406c520437dca2 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -851,9 +851,9 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (!(vport->fc_flag & FC_PT2PT)) { /* Check config parameter use-adisc or FCP-2 */ - if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || + if (vport->cfg_use_adisc && ((vport->fc_flag & FC_RSCN_MODE) || ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) && - (ndlp->nlp_type & NLP_FCP_TARGET))) { + (ndlp->nlp_type & NLP_FCP_TARGET)))) { spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_NPR_ADISC; spin_unlock_irq(shost->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index fe1097666de4375e7dfe9a0febf4ddf7d9cff026..6822cd9ff8f1ef460dea74f002d52bb7ef043b28 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -528,7 +528,6 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, list_del_init(&psb->list); psb->exch_busy = 0; psb->status = IOSTAT_SUCCESS; -#ifdef BUILD_NVME if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) { qp->abts_nvme_io_bufs--; spin_unlock(&qp->abts_io_buf_list_lock); @@ -536,7 +535,6 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, lpfc_sli4_nvme_xri_aborted(phba, axri, psb); return; } -#endif qp->abts_scsi_io_bufs--; spin_unlock(&qp->abts_io_buf_list_lock); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a0c6945b81392e1f07e02934f9702e0ac783197f..614f78dddafe0f0ae1e78b0f22beafc081b57993 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -7866,7 +7866,7 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) if (sli4_hba->hdwq) { for (eqidx = 0; eqidx < phba->cfg_irq_chann; eqidx++) { eq = phba->sli4_hba.hba_eq_hdl[eqidx].eq; - if (eq->queue_id == sli4_hba->mbx_cq->assoc_qid) { + if (eq && eq->queue_id == sli4_hba->mbx_cq->assoc_qid) { fpeq = eq; break; } diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 30bafd9d21e984461b237651358196a26eb8d514..7259bce85e0e3e54be6ed45d8cd82593685c7390 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -440,9 +440,6 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, valid = 0; if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) valid = 1; - else if (start == (ha->flt_region_boot * 4) || - start == (ha->flt_region_fw * 4)) - valid = 1; else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)) valid = 1; if (!valid) { @@ -489,8 +486,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, "Writing flash region -- 0x%x/0x%x.\n", ha->optrom_region_start, ha->optrom_region_size); - ha->isp_ops->write_optrom(vha, ha->optrom_buffer, + rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer, ha->optrom_region_start, ha->optrom_region_size); + if (rval) + rval = -EIO; break; default: rval = -EINVAL; diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 28d587a89ba61efcab7a497e8c9319a7b9272359..99f0a1a08143e0864e0ba69718945fe538ffd447 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -253,7 +253,7 @@ qla2x00_process_els(struct bsg_job *bsg_job) srb_t *sp; const char *type; int req_sg_cnt, rsp_sg_cnt; - int rval = (DRIVER_ERROR << 16); + int rval = (DID_ERROR << 16); uint16_t nextlid = 0; if (bsg_request->msgcode == FC_BSG_RPT_ELS) { @@ -432,7 +432,7 @@ qla2x00_process_ct(struct bsg_job *bsg_job) struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; - int rval = (DRIVER_ERROR << 16); + int rval = (DID_ERROR << 16); int req_sg_cnt, rsp_sg_cnt; uint16_t loop_id; struct fc_port *fcport; @@ -1950,7 +1950,7 @@ qlafx00_mgmt_cmd(struct bsg_job *bsg_job) struct Scsi_Host *host = fc_bsg_to_shost(bsg_job); scsi_qla_host_t *vha = shost_priv(host); struct qla_hw_data *ha = vha->hw; - int rval = (DRIVER_ERROR << 16); + int rval = (DID_ERROR << 16); struct qla_mt_iocb_rqst_fx00 *piocb_rqst; srb_t *sp; int req_sg_cnt = 0, rsp_sg_cnt = 0; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 4c26630c1c3eeee71a61d1080dddb3bf3474cef6..009fd5a33fcdecaf03d59ba57cf72cdfc6b84258 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2837,8 +2837,6 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) if (sense_len == 0) { rsp->status_srb = NULL; sp->done(sp, cp->result); - } else { - WARN_ON_ONCE(true); } } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 1cc6913f76c4745242b72cc7aa71e5edaae54519..4a1f21c11758ea5b8ee0e2222bfb4f05fc49dc84 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -702,6 +702,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; mcp->mb[4] = 0; + mcp->mb[11] = 0; ha->flags.using_lr_setting = 0; if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { @@ -746,7 +747,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) if (ha->flags.exchoffld_enabled) mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD; - mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1; + mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11; mcp->in_mb |= MBX_3 | MBX_2 | MBX_1; } else { mcp->mb[1] = LSW(risc_addr); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3568031c6504426b3edb6b2739a81fd169523730..337162ac3a7716c46bc18774410f7a1796e2b33a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3224,6 +3224,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out); ha->wq = alloc_workqueue("qla2xxx_wq", 0, 0); + if (unlikely(!ha->wq)) { + ret = -ENOMEM; + goto probe_failed; + } if (ha->isp_ops->initialize_adapter(base_vha)) { ql_log(ql_log_fatal, base_vha, 0x00d6, @@ -3531,6 +3535,10 @@ qla2x00_shutdown(struct pci_dev *pdev) qla2x00_try_to_stop_firmware(vha); } + /* Disable timer */ + if (vha->timer_active) + qla2x00_stop_timer(vha); + /* Turn adapter off line */ vha->flags.online = 0; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1c470e31ae815feb34ffad7b71a675aa4ce212f3..ae2fa170f6ad3f2267efd4ac6b8fd18eae8a3514 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -967,6 +967,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->result = scmd->result; + ses->resid_len = scmd->req.resid_len; ses->underflow = scmd->underflow; ses->prot_op = scmd->prot_op; ses->eh_eflags = scmd->eh_eflags; @@ -977,6 +978,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, memset(scmd->cmnd, 0, BLK_MAX_CDB); memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->result = 0; + scmd->req.resid_len = 0; if (sense_bytes) { scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE, @@ -1029,6 +1031,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->result = ses->result; + scmd->req.resid_len = ses->resid_len; scmd->underflow = ses->underflow; scmd->prot_op = ses->prot_op; scmd->eh_eflags = ses->eh_eflags; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index dc210b9d4896b738ee2a3e2b78fde8c89910004b..5447738906ac04257fe6b1d92ee1460b75c825e3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1834,6 +1834,7 @@ static const struct blk_mq_ops scsi_mq_ops_no_commit = { .init_request = scsi_mq_init_request, .exit_request = scsi_mq_exit_request, .initialize_rq_fn = scsi_initialize_rq, + .cleanup_rq = scsi_cleanup_rq, .busy = scsi_mq_lld_busy, .map_queues = scsi_map_queues, }; @@ -1921,7 +1922,8 @@ struct scsi_device *scsi_device_from_queue(struct request_queue *q) { struct scsi_device *sdev = NULL; - if (q->mq_ops == &scsi_mq_ops) + if (q->mq_ops == &scsi_mq_ops_no_commit || + q->mq_ops == &scsi_mq_ops) sdev = q->queuedata; if (!sdev || !get_device(&sdev->sdev_gendev)) sdev = NULL; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 64c96c7828ee1056042da4a913d9f3f2b9506506..fb07b4456514b853f09aa500d076c7d3c9700a2b 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -730,6 +730,14 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct kernfs_node *kn; + struct scsi_device *sdev = to_scsi_device(dev); + + /* + * We need to try to get module, avoiding the module been removed + * during delete. + */ + if (scsi_device_get(sdev)) + return -ENODEV; kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); WARN_ON_ONCE(!kn); @@ -744,9 +752,10 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr, * state into SDEV_DEL. */ device_remove_file(dev, attr); - scsi_remove_device(to_scsi_device(dev)); + scsi_remove_device(sdev); if (kn) sysfs_unbreak_active_protection(kn); + scsi_device_put(sdev); return count; }; static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete); @@ -1300,7 +1309,8 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) device_enable_async_suspend(&sdev->sdev_gendev); scsi_autopm_get_target(starget); pm_runtime_set_active(&sdev->sdev_gendev); - pm_runtime_forbid(&sdev->sdev_gendev); + if (!sdev->rpm_autosuspend) + pm_runtime_forbid(&sdev->sdev_gendev); pm_runtime_enable(&sdev->sdev_gendev); scsi_autopm_put_target(starget); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 50928bc266eb24d5995affc32f7de12ec1ca49b2..aab4ed891427bcfe6448fd5724b95dc82844ee2d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1166,11 +1166,12 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) sector_t lba = sectors_to_logical(sdp, blk_rq_pos(rq)); sector_t threshold; unsigned int nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq)); - bool dif, dix; unsigned int mask = logical_to_sectors(sdp, 1) - 1; bool write = rq_data_dir(rq) == WRITE; unsigned char protect, fua; blk_status_t ret; + unsigned int dif; + bool dix; ret = scsi_init_io(cmd); if (ret != BLK_STS_OK) @@ -1654,7 +1655,8 @@ static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr) /* we need to evaluate the error return */ if (scsi_sense_valid(sshdr) && (sshdr->asc == 0x3a || /* medium not present */ - sshdr->asc == 0x20)) /* invalid command */ + sshdr->asc == 0x20 || /* invalid command */ + (sshdr->asc == 0x74 && sshdr->ascq == 0x71))) /* drive is password locked */ /* this is no error here */ return 0; @@ -3367,6 +3369,10 @@ static int sd_probe(struct device *dev) } blk_pm_runtime_init(sdp->request_queue, dev); + if (sdp->rpm_autosuspend) { + pm_runtime_set_autosuspend_delay(dev, + sdp->host->hostt->rpm_autosuspend_delay); + } device_add_disk(dev, gd, NULL); if (sdkp->capacity) sd_dif_config_host(sdkp); diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c index aef4881d8e21588f7698aeccb982ae416e6972ff..a85d52b5dc32094d04219b548619c2b7ea1de23f 100644 --- a/drivers/scsi/sni_53c710.c +++ b/drivers/scsi/sni_53c710.c @@ -66,10 +66,8 @@ static int snirm710_probe(struct platform_device *dev) base = res->start; hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); - if (!hostdata) { - dev_printk(KERN_ERR, dev, "Failed to allocate host data\n"); + if (!hostdata) return -ENOMEM; - } hostdata->dev = &dev->dev; dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index 0b845ab7c3bf19f5585b61bd7dcfb4e92760597f..3ee5cede823ea80c6a29b55845cfbc2a43734177 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -150,3 +150,12 @@ config SCSI_UFS_BSG Select this if you need a bsg device node for your UFS controller. If unsure, say N. + +config SCSI_UFS_CRYPTO + bool "UFS Crypto Engine Support" + depends on SCSI_UFSHCD && BLK_INLINE_ENCRYPTION + help + Enable Crypto Engine Support in UFS. + Enabling this makes it possible for the kernel to use the crypto + capabilities of the UFS device (if present) to perform crypto + operations on data being transferred to/from the device. diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 2a9097939bcb55f794933c5d894eabae691dfa2c..094c39989a376664055a6b4330eb78f617dd320f 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o +ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO) += ufshcd-crypto.o diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 1f6c24e7bc3c175029d5d65c916fd569d11252d3..47fad62d584d33b3f95996c58404577819c64903 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1464,18 +1464,27 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, int err = 0; if (status == PRE_CHANGE) { + err = ufshcd_uic_hibern8_enter(hba); + if (err) + return err; if (scale_up) err = ufs_qcom_clk_scale_up_pre_change(hba); else err = ufs_qcom_clk_scale_down_pre_change(hba); + if (err) + ufshcd_uic_hibern8_exit(hba); + } else { if (scale_up) err = ufs_qcom_clk_scale_up_post_change(hba); else err = ufs_qcom_clk_scale_down_post_change(hba); - if (err || !dev_req_params) + + if (err || !dev_req_params) { + ufshcd_uic_hibern8_exit(hba); goto out; + } ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, @@ -1483,6 +1492,7 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, dev_req_params->hs_rate, false); ufs_qcom_update_bus_bw_vote(host); + ufshcd_uic_hibern8_exit(hba); } out: diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index a9344eb4e047f1e73c28212024c1e8dcefb19228..dc2f6d2b46edc306f8696cd4471358a86dd6df49 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -98,6 +98,8 @@ static int ufs_bsg_request(struct bsg_job *job) bsg_reply->reply_payload_rcv_len = 0; + pm_runtime_get_sync(hba->dev); + msgcode = bsg_request->msgcode; switch (msgcode) { case UPIU_TRANSACTION_QUERY_REQ: @@ -135,6 +137,8 @@ static int ufs_bsg_request(struct bsg_job *job) break; } + pm_runtime_put_sync(hba->dev); + if (!desc_buff) goto out; diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c new file mode 100644 index 0000000000000000000000000000000000000000..988d8df8f3949bc0ea77db1031f9fc87ed91fba2 --- /dev/null +++ b/drivers/scsi/ufs/ufshcd-crypto.c @@ -0,0 +1,523 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + */ + +#include + +#include "ufshcd.h" +#include "ufshcd-crypto.h" + +static bool ufshcd_cap_idx_valid(struct ufs_hba *hba, unsigned int cap_idx) +{ + return cap_idx < hba->crypto_capabilities.num_crypto_cap; +} + +static u8 get_data_unit_size_mask(unsigned int data_unit_size) +{ + if (data_unit_size < 512 || data_unit_size > 65536 || + !is_power_of_2(data_unit_size)) + return 0; + + return data_unit_size / 512; +} + +static size_t get_keysize_bytes(enum ufs_crypto_key_size size) +{ + switch (size) { + case UFS_CRYPTO_KEY_SIZE_128: return 16; + case UFS_CRYPTO_KEY_SIZE_192: return 24; + case UFS_CRYPTO_KEY_SIZE_256: return 32; + case UFS_CRYPTO_KEY_SIZE_512: return 64; + default: return 0; + } +} + +static int ufshcd_crypto_cap_find(void *hba_p, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + struct ufs_hba *hba = hba_p; + enum ufs_crypto_alg ufs_alg; + u8 data_unit_mask; + int cap_idx; + enum ufs_crypto_key_size ufs_key_size; + union ufs_crypto_cap_entry *ccap_array = hba->crypto_cap_array; + + if (!ufshcd_hba_is_crypto_supported(hba)) + return -EINVAL; + + switch (crypto_mode) { + case BLK_ENCRYPTION_MODE_AES_256_XTS: + ufs_alg = UFS_CRYPTO_ALG_AES_XTS; + ufs_key_size = UFS_CRYPTO_KEY_SIZE_256; + break; + default: return -EINVAL; + } + + data_unit_mask = get_data_unit_size_mask(data_unit_size); + + for (cap_idx = 0; cap_idx < hba->crypto_capabilities.num_crypto_cap; + cap_idx++) { + if (ccap_array[cap_idx].algorithm_id == ufs_alg && + (ccap_array[cap_idx].sdus_mask & data_unit_mask) && + ccap_array[cap_idx].key_size == ufs_key_size) + return cap_idx; + } + + return -EINVAL; +} + +/** + * ufshcd_crypto_cfg_entry_write_key - Write a key into a crypto_cfg_entry + * + * Writes the key with the appropriate format - for AES_XTS, + * the first half of the key is copied as is, the second half is + * copied with an offset halfway into the cfg->crypto_key array. + * For the other supported crypto algs, the key is just copied. + * + * @cfg: The crypto config to write to + * @key: The key to write + * @cap: The crypto capability (which specifies the crypto alg and key size) + * + * Returns 0 on success, or -EINVAL + */ +static int ufshcd_crypto_cfg_entry_write_key(union ufs_crypto_cfg_entry *cfg, + const u8 *key, + union ufs_crypto_cap_entry cap) +{ + size_t key_size_bytes = get_keysize_bytes(cap.key_size); + + if (key_size_bytes == 0) + return -EINVAL; + + switch (cap.algorithm_id) { + case UFS_CRYPTO_ALG_AES_XTS: + key_size_bytes *= 2; + if (key_size_bytes > UFS_CRYPTO_KEY_MAX_SIZE) + return -EINVAL; + + memcpy(cfg->crypto_key, key, key_size_bytes/2); + memcpy(cfg->crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2, + key + key_size_bytes/2, key_size_bytes/2); + return 0; + case UFS_CRYPTO_ALG_BITLOCKER_AES_CBC: // fallthrough + case UFS_CRYPTO_ALG_AES_ECB: // fallthrough + case UFS_CRYPTO_ALG_ESSIV_AES_CBC: + memcpy(cfg->crypto_key, key, key_size_bytes); + return 0; + } + + return -EINVAL; +} + +static void program_key(struct ufs_hba *hba, + const union ufs_crypto_cfg_entry *cfg, + int slot) +{ + int i; + u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg); + + /* Clear the dword 16 */ + ufshcd_writel(hba, 0, slot_offset + 16 * sizeof(cfg->reg_val[0])); + /* Ensure that CFGE is cleared before programming the key */ + wmb(); + for (i = 0; i < 16; i++) { + ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[i]), + slot_offset + i * sizeof(cfg->reg_val[0])); + /* Spec says each dword in key must be written sequentially */ + wmb(); + } + /* Write dword 17 */ + ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[17]), + slot_offset + 17 * sizeof(cfg->reg_val[0])); + /* Dword 16 must be written last */ + wmb(); + /* Write dword 16 */ + ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[16]), + slot_offset + 16 * sizeof(cfg->reg_val[0])); + wmb(); +} + +static int ufshcd_crypto_keyslot_program(void *hba_p, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size, + unsigned int slot) +{ + struct ufs_hba *hba = hba_p; + int err = 0; + u8 data_unit_mask; + union ufs_crypto_cfg_entry cfg; + union ufs_crypto_cfg_entry *cfg_arr = hba->crypto_cfgs; + int cap_idx; + + cap_idx = ufshcd_crypto_cap_find(hba_p, crypto_mode, + data_unit_size); + + if (!ufshcd_is_crypto_enabled(hba) || + !ufshcd_keyslot_valid(hba, slot) || + !ufshcd_cap_idx_valid(hba, cap_idx)) + return -EINVAL; + + data_unit_mask = get_data_unit_size_mask(data_unit_size); + + if (!(data_unit_mask & hba->crypto_cap_array[cap_idx].sdus_mask)) + return -EINVAL; + + memset(&cfg, 0, sizeof(cfg)); + cfg.data_unit_size = data_unit_mask; + cfg.crypto_cap_idx = cap_idx; + cfg.config_enable |= UFS_CRYPTO_CONFIGURATION_ENABLE; + + err = ufshcd_crypto_cfg_entry_write_key(&cfg, key, + hba->crypto_cap_array[cap_idx]); + if (err) + return err; + + program_key(hba, &cfg, slot); + + memcpy(&cfg_arr[slot], &cfg, sizeof(cfg)); + memzero_explicit(&cfg, sizeof(cfg)); + + return 0; +} + +static int ufshcd_crypto_keyslot_find(void *hba_p, + const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + struct ufs_hba *hba = hba_p; + int err = 0; + int slot; + u8 data_unit_mask; + union ufs_crypto_cfg_entry cfg; + union ufs_crypto_cfg_entry *cfg_arr = hba->crypto_cfgs; + int cap_idx; + + cap_idx = ufshcd_crypto_cap_find(hba_p, crypto_mode, + data_unit_size); + + if (!ufshcd_is_crypto_enabled(hba) || + !ufshcd_cap_idx_valid(hba, cap_idx)) + return -EINVAL; + + data_unit_mask = get_data_unit_size_mask(data_unit_size); + + if (!(data_unit_mask & hba->crypto_cap_array[cap_idx].sdus_mask)) + return -EINVAL; + + memset(&cfg, 0, sizeof(cfg)); + err = ufshcd_crypto_cfg_entry_write_key(&cfg, key, + hba->crypto_cap_array[cap_idx]); + + if (err) + return -EINVAL; + + for (slot = 0; slot < NUM_KEYSLOTS(hba); slot++) { + if ((cfg_arr[slot].config_enable & + UFS_CRYPTO_CONFIGURATION_ENABLE) && + data_unit_mask == cfg_arr[slot].data_unit_size && + cap_idx == cfg_arr[slot].crypto_cap_idx && + !crypto_memneq(&cfg.crypto_key, cfg_arr[slot].crypto_key, + UFS_CRYPTO_KEY_MAX_SIZE)) { + memzero_explicit(&cfg, sizeof(cfg)); + return slot; + } + } + + memzero_explicit(&cfg, sizeof(cfg)); + return -ENOKEY; +} + +static int ufshcd_crypto_keyslot_evict(void *hba_p, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size, + unsigned int slot) +{ + struct ufs_hba *hba = hba_p; + int i = 0; + u32 reg_base; + union ufs_crypto_cfg_entry *cfg_arr = hba->crypto_cfgs; + + if (!ufshcd_is_crypto_enabled(hba) || + !ufshcd_keyslot_valid(hba, slot)) + return -EINVAL; + + memset(&cfg_arr[slot], 0, sizeof(cfg_arr[slot])); + reg_base = hba->crypto_cfg_register + slot * sizeof(cfg_arr[0]); + + /* + * Clear the crypto cfg on the device. Clearing CFGE + * might not be sufficient, so just clear the entire cfg. + */ + for (i = 0; i < sizeof(cfg_arr[0]); i += sizeof(__le32)) + ufshcd_writel(hba, 0, reg_base + i); + wmb(); + + return 0; +} + +static bool ufshcd_crypto_mode_supported(void *hba_p, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + return ufshcd_crypto_cap_find(hba_p, crypto_mode, data_unit_size) >= 0; +} + +/* Functions implementing UFSHCI v2.1 specification behaviour */ +void ufshcd_crypto_enable_spec(struct ufs_hba *hba) +{ + union ufs_crypto_cfg_entry *cfg_arr = hba->crypto_cfgs; + int slot; + + if (!ufshcd_hba_is_crypto_supported(hba)) + return; + + hba->caps |= UFSHCD_CAP_CRYPTO; + /* + * Reset might clear all keys, so reprogram all the keys. + * Also serves to clear keys on driver init. + */ + for (slot = 0; slot < NUM_KEYSLOTS(hba); slot++) + program_key(hba, &cfg_arr[slot], slot); +} +EXPORT_SYMBOL(ufshcd_crypto_enable_spec); + +void ufshcd_crypto_disable_spec(struct ufs_hba *hba) +{ + hba->caps &= ~UFSHCD_CAP_CRYPTO; +} +EXPORT_SYMBOL(ufshcd_crypto_disable_spec); + +static const struct keyslot_mgmt_ll_ops ufshcd_ksm_ops = { + .keyslot_program = ufshcd_crypto_keyslot_program, + .keyslot_evict = ufshcd_crypto_keyslot_evict, + .keyslot_find = ufshcd_crypto_keyslot_find, + .crypto_mode_supported = ufshcd_crypto_mode_supported, +}; + +/** + * ufshcd_hba_init_crypto - Read crypto capabilities, init crypto fields in hba + * @hba: Per adapter instance + * + * Returns 0 on success. Returns -ENODEV if such capabilities don't exist, and + * -ENOMEM upon OOM. + */ +int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba, + const struct keyslot_mgmt_ll_ops *ksm_ops) +{ + int cap_idx = 0; + int err = 0; + + /* Default to disabling crypto */ + hba->caps &= ~UFSHCD_CAP_CRYPTO; + + if (!(hba->capabilities & MASK_CRYPTO_SUPPORT)) { + err = -ENODEV; + goto out; + } + + /* + * Crypto Capabilities should never be 0, because the + * config_array_ptr > 04h. So we use a 0 value to indicate that + * crypto init failed, and can't be enabled. + */ + hba->crypto_capabilities.reg_val = + cpu_to_le32(ufshcd_readl(hba, REG_UFS_CCAP)); + hba->crypto_cfg_register = + (u32)hba->crypto_capabilities.config_array_ptr * 0x100; + hba->crypto_cap_array = + devm_kcalloc(hba->dev, + hba->crypto_capabilities.num_crypto_cap, + sizeof(hba->crypto_cap_array[0]), + GFP_KERNEL); + if (!hba->crypto_cap_array) { + err = -ENOMEM; + goto out; + } + + hba->crypto_cfgs = + devm_kcalloc(hba->dev, + NUM_KEYSLOTS(hba), + sizeof(hba->crypto_cfgs[0]), + GFP_KERNEL); + if (!hba->crypto_cfgs) { + err = -ENOMEM; + goto out_free_cfg_mem; + } + + /* + * Store all the capabilities now so that we don't need to repeatedly + * access the device each time we want to know its capabilities + */ + for (cap_idx = 0; cap_idx < hba->crypto_capabilities.num_crypto_cap; + cap_idx++) { + hba->crypto_cap_array[cap_idx].reg_val = + cpu_to_le32(ufshcd_readl(hba, + REG_UFS_CRYPTOCAP + + cap_idx * sizeof(__le32))); + } + + hba->ksm = keyslot_manager_create(NUM_KEYSLOTS(hba), ksm_ops, hba); + + if (!hba->ksm) { + err = -ENOMEM; + goto out_free_crypto_cfgs; + } + + return 0; +out_free_crypto_cfgs: + devm_kfree(hba->dev, hba->crypto_cfgs); +out_free_cfg_mem: + devm_kfree(hba->dev, hba->crypto_cap_array); +out: + // TODO: print error? + /* Indicate that init failed by setting crypto_capabilities to 0 */ + hba->crypto_capabilities.reg_val = 0; + return err; +} +EXPORT_SYMBOL(ufshcd_hba_init_crypto_spec); + +void ufshcd_crypto_setup_rq_keyslot_manager_spec(struct ufs_hba *hba, + struct request_queue *q) +{ + if (!ufshcd_hba_is_crypto_supported(hba) || !q) + return; + + q->ksm = hba->ksm; +} +EXPORT_SYMBOL(ufshcd_crypto_setup_rq_keyslot_manager_spec); + +void ufshcd_crypto_destroy_rq_keyslot_manager_spec(struct ufs_hba *hba, + struct request_queue *q) +{ + keyslot_manager_destroy(hba->ksm); +} +EXPORT_SYMBOL(ufshcd_crypto_destroy_rq_keyslot_manager_spec); + +int ufshcd_prepare_lrbp_crypto_spec(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp) +{ + int key_slot; + + if (!cmd->request->bio || + !bio_crypt_should_process(cmd->request->bio, cmd->request->q)) { + lrbp->crypto_enable = false; + return 0; + } + + if (WARN_ON(!ufshcd_is_crypto_enabled(hba))) { + /* + * Upper layer asked us to do inline encryption + * but that isn't enabled, so we fail this request. + */ + return -EINVAL; + } + key_slot = bio_crypt_get_keyslot(cmd->request->bio); + if (!ufshcd_keyslot_valid(hba, key_slot)) + return -EINVAL; + + lrbp->crypto_enable = true; + lrbp->crypto_key_slot = key_slot; + lrbp->data_unit_num = bio_crypt_data_unit_num(cmd->request->bio); + + return 0; +} +EXPORT_SYMBOL(ufshcd_prepare_lrbp_crypto_spec); + +/* Crypto Variant Ops Support */ + +void ufshcd_crypto_enable(struct ufs_hba *hba) +{ + if (hba->crypto_vops && hba->crypto_vops->enable) + return hba->crypto_vops->enable(hba); + + return ufshcd_crypto_enable_spec(hba); +} + +void ufshcd_crypto_disable(struct ufs_hba *hba) +{ + if (hba->crypto_vops && hba->crypto_vops->disable) + return hba->crypto_vops->disable(hba); + + return ufshcd_crypto_disable_spec(hba); +} + +int ufshcd_hba_init_crypto(struct ufs_hba *hba) +{ + if (hba->crypto_vops && hba->crypto_vops->hba_init_crypto) + return hba->crypto_vops->hba_init_crypto(hba, + &ufshcd_ksm_ops); + + return ufshcd_hba_init_crypto_spec(hba, &ufshcd_ksm_ops); +} + +void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba, + struct request_queue *q) +{ + if (hba->crypto_vops && hba->crypto_vops->setup_rq_keyslot_manager) + return hba->crypto_vops->setup_rq_keyslot_manager(hba, q); + + return ufshcd_crypto_setup_rq_keyslot_manager_spec(hba, q); +} + +void ufshcd_crypto_destroy_rq_keyslot_manager(struct ufs_hba *hba, + struct request_queue *q) +{ + if (hba->crypto_vops && hba->crypto_vops->destroy_rq_keyslot_manager) + return hba->crypto_vops->destroy_rq_keyslot_manager(hba, q); + + return ufshcd_crypto_destroy_rq_keyslot_manager_spec(hba, q); +} + +int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp) +{ + if (hba->crypto_vops && hba->crypto_vops->prepare_lrbp_crypto) + return hba->crypto_vops->prepare_lrbp_crypto(hba, cmd, lrbp); + + return ufshcd_prepare_lrbp_crypto_spec(hba, cmd, lrbp); +} + +int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp) +{ + if (hba->crypto_vops && hba->crypto_vops->complete_lrbp_crypto) + return hba->crypto_vops->complete_lrbp_crypto(hba, cmd, lrbp); + + return 0; +} + +void ufshcd_crypto_debug(struct ufs_hba *hba) +{ + if (hba->crypto_vops && hba->crypto_vops->debug) + hba->crypto_vops->debug(hba); +} + +int ufshcd_crypto_suspend(struct ufs_hba *hba, + enum ufs_pm_op pm_op) +{ + if (hba->crypto_vops && hba->crypto_vops->suspend) + return hba->crypto_vops->suspend(hba, pm_op); + + return 0; +} + +int ufshcd_crypto_resume(struct ufs_hba *hba, + enum ufs_pm_op pm_op) +{ + if (hba->crypto_vops && hba->crypto_vops->resume) + return hba->crypto_vops->resume(hba, pm_op); + + return 0; +} + +void ufshcd_crypto_set_vops(struct ufs_hba *hba, + struct ufs_hba_crypto_variant_ops *crypto_vops) +{ + hba->crypto_vops = crypto_vops; +} diff --git a/drivers/scsi/ufs/ufshcd-crypto.h b/drivers/scsi/ufs/ufshcd-crypto.h new file mode 100644 index 0000000000000000000000000000000000000000..3c03d0e23e8719619800cd7839af4d281f37511e --- /dev/null +++ b/drivers/scsi/ufs/ufshcd-crypto.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + */ + +#ifndef _UFSHCD_CRYPTO_H +#define _UFSHCD_CRYPTO_H + +#ifdef CONFIG_SCSI_UFS_CRYPTO +#include +#include "ufshcd.h" +#include "ufshci.h" + +#define NUM_KEYSLOTS(hba) (hba->crypto_capabilities.config_count + 1) + +static inline bool ufshcd_keyslot_valid(struct ufs_hba *hba, unsigned int slot) +{ + /* + * The actual number of configurations supported is (CFGC+1), so slot + * numbers range from 0 to config_count inclusive. + */ + return slot < NUM_KEYSLOTS(hba); +} + +static inline bool ufshcd_hba_is_crypto_supported(struct ufs_hba *hba) +{ + return hba->crypto_capabilities.reg_val != 0; +} + +static inline bool ufshcd_is_crypto_enabled(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_CRYPTO; +} + +/* Functions implementing UFSHCI v2.1 specification behaviour */ +int ufshcd_prepare_lrbp_crypto_spec(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp); + +void ufshcd_crypto_enable_spec(struct ufs_hba *hba); + +void ufshcd_crypto_disable_spec(struct ufs_hba *hba); + +struct keyslot_mgmt_ll_ops; +int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba, + const struct keyslot_mgmt_ll_ops *ksm_ops); + +void ufshcd_crypto_setup_rq_keyslot_manager_spec(struct ufs_hba *hba, + struct request_queue *q); + +void ufshcd_crypto_destroy_rq_keyslot_manager_spec(struct ufs_hba *hba, + struct request_queue *q); + +/* Crypto Variant Ops Support */ +void ufshcd_crypto_enable(struct ufs_hba *hba); + +void ufshcd_crypto_disable(struct ufs_hba *hba); + +int ufshcd_hba_init_crypto(struct ufs_hba *hba); + +void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba, + struct request_queue *q); + +void ufshcd_crypto_destroy_rq_keyslot_manager(struct ufs_hba *hba, + struct request_queue *q); + +int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp); + +int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp); + +void ufshcd_crypto_debug(struct ufs_hba *hba); + +int ufshcd_crypto_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op); + +int ufshcd_crypto_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op); + +void ufshcd_crypto_set_vops(struct ufs_hba *hba, + struct ufs_hba_crypto_variant_ops *crypto_vops); + +#else /* CONFIG_SCSI_UFS_CRYPTO */ + +static inline bool ufshcd_keyslot_valid(struct ufs_hba *hba, + unsigned int slot) +{ + return false; +} + +static inline bool ufshcd_hba_is_crypto_supported(struct ufs_hba *hba) +{ + return false; +} + +static inline bool ufshcd_is_crypto_enabled(struct ufs_hba *hba) +{ + return false; +} + +static inline void ufshcd_crypto_enable(struct ufs_hba *hba) { } + +static inline void ufshcd_crypto_disable(struct ufs_hba *hba) { } + +static inline int ufshcd_hba_init_crypto(struct ufs_hba *hba) +{ + return 0; +} + +static inline void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba, + struct request_queue *q) { } + +static inline void ufshcd_crypto_destroy_rq_keyslot_manager(struct ufs_hba *hba, + struct request_queue *q) { } + +static inline int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp) +{ + lrbp->crypto_enable = false; + return 0; +} + +static inline int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp) +{ + return 0; +} + +static inline void ufshcd_crypto_debug(struct ufs_hba *hba) { } + +static inline int ufshcd_crypto_suspend(struct ufs_hba *hba, + enum ufs_pm_op pm_op) +{ + return 0; +} + +static inline int ufshcd_crypto_resume(struct ufs_hba *hba, + enum ufs_pm_op pm_op) +{ + return 0; +} + +static inline void ufshcd_crypto_set_vops(struct ufs_hba *hba, + struct ufs_hba_crypto_variant_ops *crypto_vops) { } + +#endif /* CONFIG_SCSI_UFS_CRYPTO */ + +#endif /* _UFSHCD_CRYPTO_H */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 34e22667baf9f9f577db64dfa2e9d6043dbb3b3d..578188b5f953ba34c2ed5d8149db51c32fc2b476 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -47,6 +47,7 @@ #include "unipro.h" #include "ufs-sysfs.h" #include "ufs_bsg.h" +#include "ufshcd-crypto.h" #define CREATE_TRACE_POINTS #include @@ -88,6 +89,9 @@ /* Interrupt aggregation default timeout, unit: 40us */ #define INT_AGGR_DEF_TO 0x02 +/* default delay of autosuspend: 2000 ms */ +#define RPM_AUTOSUSPEND_DELAY_MS 2000 + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -247,8 +251,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba); static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, bool skip_ref_clk); static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); -static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); -static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); static int ufshcd_host_reset_and_restore(struct ufs_hba *hba); static void ufshcd_resume_clkscaling(struct ufs_hba *hba); @@ -433,6 +435,10 @@ static void ufshcd_print_host_regs(struct ufs_hba *hba) ufshcd_print_clk_freqs(hba); + if (hba->vops && hba->vops->dbg_register_dump) + hba->vops->dbg_register_dump(hba); + + ufshcd_crypto_debug(hba); } static @@ -855,7 +861,14 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba) */ static inline void ufshcd_hba_start(struct ufs_hba *hba) { - ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE); + u32 val = CONTROLLER_ENABLE; + + if (ufshcd_hba_is_crypto_supported(hba)) { + ufshcd_crypto_enable(hba); + val |= CRYPTO_GENERAL_ENABLE; + } + + ufshcd_writel(hba, val, REG_CONTROLLER_ENABLE); } /** @@ -2209,9 +2222,21 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, dword_0 |= UTP_REQ_DESC_INT_CMD; /* Transfer request descriptor header fields */ + if (lrbp->crypto_enable) { + dword_0 |= UTP_REQ_DESC_CRYPTO_ENABLE_CMD; + dword_0 |= lrbp->crypto_key_slot; + req_desc->header.dword_1 = + cpu_to_le32((u32)lrbp->data_unit_num); + req_desc->header.dword_3 = + cpu_to_le32((u32)(lrbp->data_unit_num >> 32)); + } else { + /* dword_1 and dword_3 are reserved, hence they are set to 0 */ + req_desc->header.dword_1 = 0; + req_desc->header.dword_3 = 0; + } + req_desc->header.dword_0 = cpu_to_le32(dword_0); - /* dword_1 is reserved, hence it is set to 0 */ - req_desc->header.dword_1 = 0; + /* * assigning invalid value for command status. Controller * updates OCS on command completion, with the command @@ -2219,8 +2244,6 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, */ req_desc->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS); - /* dword_3 is reserved, hence it is set to 0 */ - req_desc->header.dword_3 = 0; req_desc->prd_table_length = 0; } @@ -2467,6 +2490,13 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) lrbp->task_tag = tag; lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun); lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false; + + err = ufshcd_prepare_lrbp_crypto(hba, cmd, lrbp); + if (err) { + lrbp->cmd = NULL; + clear_bit_unlock(tag, &hba->lrb_in_use); + goto out; + } lrbp->req_abort_skip = false; ufshcd_comp_scsi_upiu(hba, lrbp); @@ -2500,6 +2530,7 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba, lrbp->task_tag = tag; lrbp->lun = 0; /* device management cmd is not specific to any LUN */ lrbp->intr_cmd = true; /* No interrupt aggregation */ + lrbp->crypto_enable = false; /* No crypto operations */ hba->dev_cmd.type = cmd_type; return ufshcd_comp_devman_upiu(hba, lrbp); @@ -3899,7 +3930,7 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba) return ret; } -static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba) +int ufshcd_uic_hibern8_enter(struct ufs_hba *hba) { int ret = 0, retries; @@ -3911,8 +3942,9 @@ static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba) out: return ret; } +EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_enter); -static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) +int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) { struct uic_command uic_cmd = {0}; int ret; @@ -3938,6 +3970,7 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) return ret; } +EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_exit); static void ufshcd_auto_hibern8_enable(struct ufs_hba *hba) { @@ -4228,6 +4261,8 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep) { int err; + ufshcd_crypto_disable(hba); + ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE); err = ufshcd_wait_for_register(hba, REG_CONTROLLER_ENABLE, CONTROLLER_ENABLE, CONTROLLER_DISABLE, @@ -4631,8 +4666,15 @@ static int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth) static int ufshcd_slave_configure(struct scsi_device *sdev) { struct request_queue *q = sdev->request_queue; + struct ufs_hba *hba = shost_priv(sdev->host); blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); + + ufshcd_crypto_setup_rq_keyslot_manager(hba, q); + + if (ufshcd_is_rpm_autosuspend_allowed(hba)) + sdev->rpm_autosuspend = 1; + return 0; } @@ -4643,6 +4685,7 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) static void ufshcd_slave_destroy(struct scsi_device *sdev) { struct ufs_hba *hba; + struct request_queue *q = sdev->request_queue; hba = shost_priv(sdev->host); /* Drop the reference as it won't be needed anymore */ @@ -4653,6 +4696,8 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev) hba->sdev_ufs_device = NULL; spin_unlock_irqrestore(hba->host->host_lock, flags); } + + ufshcd_crypto_destroy_rq_keyslot_manager(hba, q); } /** @@ -4768,6 +4813,8 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) case OCS_MISMATCH_RESP_UPIU_SIZE: case OCS_PEER_COMM_FAILURE: case OCS_FATAL_ERROR: + case OCS_INVALID_CRYPTO_CONFIG: + case OCS_GENERAL_CRYPTO_ERROR: default: result |= DID_ERROR << 16; dev_err(hba->dev, @@ -4823,6 +4870,7 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, result = ufshcd_transfer_rsp_status(hba, lrbp); scsi_dma_unmap(cmd); cmd->result = result; + ufshcd_complete_lrbp_crypto(hba, cmd, lrbp); /* Mark completed command as NULL in LRB */ lrbp->cmd = NULL; clear_bit_unlock(index, &hba->lrb_in_use); @@ -7073,6 +7121,7 @@ static struct scsi_host_template ufshcd_driver_template = { .track_queue_depth = 1, .sdev_groups = ufshcd_driver_groups, .dma_boundary = PAGE_SIZE - 1, + .rpm_autosuspend_delay = RPM_AUTOSUSPEND_DELAY_MS, }; static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg, @@ -7766,6 +7815,10 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) req_link_state = UIC_LINK_OFF_STATE; } + ret = ufshcd_crypto_suspend(hba, pm_op); + if (ret) + goto out; + /* * If we can't transition into any of the low power modes * just gate the clocks. @@ -7869,6 +7922,7 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) ufshcd_resume_clkscaling(hba); hba->clk_gating.is_suspended = false; ufshcd_release(hba); + ufshcd_crypto_resume(hba, pm_op); out: hba->pm_op_in_progress = 0; if (ret) @@ -7890,9 +7944,11 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) { int ret; enum uic_link_state old_link_state; + enum ufs_dev_pwr_mode old_pwr_mode; hba->pm_op_in_progress = 1; old_link_state = hba->uic_link_state; + old_pwr_mode = hba->curr_dev_pwr_mode; ufshcd_hba_vreg_set_hpm(hba); /* Make sure clocks are enabled before accessing controller */ @@ -7940,6 +7996,10 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) goto set_old_link_state; } + ret = ufshcd_crypto_resume(hba, pm_op); + if (ret) + goto set_old_dev_pwr_mode; + if (ufshcd_keep_autobkops_enabled_except_suspend(hba)) ufshcd_enable_auto_bkops(hba); else @@ -7962,6 +8022,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) goto out; +set_old_dev_pwr_mode: + if (old_pwr_mode != hba->curr_dev_pwr_mode) + ufshcd_set_dev_pwr_mode(hba, old_pwr_mode); set_old_link_state: ufshcd_link_state_transition(hba, old_link_state, 0); vendor_suspend: @@ -8382,6 +8445,13 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Reset the attached device */ ufshcd_vops_device_reset(hba); + /* Init crypto */ + err = ufshcd_hba_init_crypto(hba); + if (err) { + dev_err(hba->dev, "crypto setup failed\n"); + goto out_remove_scsi_host; + } + /* Host controller enable */ err = ufshcd_hba_enable(hba); if (err) { diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 4db64eec051443ce30818f1ca95503a917e9bf95..74f80052045c50ad69e0e75ab9ec5417424caa6e 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -169,6 +169,9 @@ struct ufs_pm_lvl_states { * @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation) * @issue_time_stamp: time stamp for debug purposes * @compl_time_stamp: time stamp for statistics + * @crypto_enable: whether or not the request needs inline crypto operations + * @crypto_key_slot: the key slot to use for inline crypto + * @data_unit_num: the data unit number for the first block for inline crypto * @req_abort_skip: skip request abort task flag */ struct ufshcd_lrb { @@ -193,6 +196,9 @@ struct ufshcd_lrb { bool intr_cmd; ktime_t issue_time_stamp; ktime_t compl_time_stamp; + bool crypto_enable; + u8 crypto_key_slot; + u64 data_unit_num; bool req_abort_skip; }; @@ -332,6 +338,28 @@ struct ufs_hba_variant_ops { void (*device_reset)(struct ufs_hba *hba); }; +struct keyslot_mgmt_ll_ops; +struct ufs_hba_crypto_variant_ops { + void (*setup_rq_keyslot_manager)(struct ufs_hba *hba, + struct request_queue *q); + void (*destroy_rq_keyslot_manager)(struct ufs_hba *hba, + struct request_queue *q); + int (*hba_init_crypto)(struct ufs_hba *hba, + const struct keyslot_mgmt_ll_ops *ksm_ops); + void (*enable)(struct ufs_hba *hba); + void (*disable)(struct ufs_hba *hba); + int (*suspend)(struct ufs_hba *hba, enum ufs_pm_op pm_op); + int (*resume)(struct ufs_hba *hba, enum ufs_pm_op pm_op); + int (*debug)(struct ufs_hba *hba); + int (*prepare_lrbp_crypto)(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp); + int (*complete_lrbp_crypto)(struct ufs_hba *hba, + struct scsi_cmnd *cmd, + struct ufshcd_lrb *lrbp); + void *priv; +}; + /* clock gating state */ enum clk_gating_state { CLKS_OFF, @@ -527,6 +555,11 @@ struct ufs_stats { * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for * device is known or not. * @scsi_block_reqs_cnt: reference counting for scsi block requests + * @crypto_capabilities: Content of crypto capabilities register (0x100) + * @crypto_cap_array: Array of crypto capabilities + * @crypto_cfg_register: Start of the crypto cfg array + * @crypto_cfgs: Array of crypto configurations (i.e. config for each slot) + * @ksm: the keyslot manager tied to this hba */ struct ufs_hba { void __iomem *mmio_base; @@ -574,6 +607,7 @@ struct ufs_hba { u32 ufs_version; const struct ufs_hba_variant_ops *vops; void *priv; + const struct ufs_hba_crypto_variant_ops *crypto_vops; unsigned int irq; bool is_irq_enabled; enum ufs_ref_clk_freq dev_ref_clk_freq; @@ -718,6 +752,17 @@ struct ufs_hba { * the performance of ongoing read/write operations. */ #define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) + /* + * This capability allows the host controller driver to use the + * inline crypto engine, if it is present + */ +#define UFSHCD_CAP_CRYPTO (1 << 6) + /* + * This capability allows host controller driver to automatically + * enable runtime power management by itself instead of waiting + * for userspace to control the power management. + */ +#define UFSHCD_CAP_RPM_AUTOSUSPEND (1 << 6) struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; @@ -732,6 +777,15 @@ struct ufs_hba { struct device bsg_dev; struct request_queue *bsg_queue; + +#ifdef CONFIG_SCSI_UFS_CRYPTO + /* crypto */ + union ufs_crypto_capabilities crypto_capabilities; + union ufs_crypto_cap_entry *crypto_cap_array; + u32 crypto_cfg_register; + union ufs_crypto_cfg_entry *crypto_cfgs; + struct keyslot_manager *ksm; +#endif /* CONFIG_SCSI_UFS_CRYPTO */ }; /* Returns true if clocks can be gated. Otherwise false */ @@ -751,6 +805,10 @@ static inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba) { return hba->caps & UFSHCD_CAP_AUTO_BKOPS_SUSPEND; } +static inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_RPM_AUTOSUSPEND; +} static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba) { @@ -1099,5 +1157,6 @@ static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun) int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len, const char *prefix); - +int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); +int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); #endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index dbb75cd28dc8a23787be8223e8be8134855c971a..291f6c3e79dbac30c7eb1d7a10e64d73e12ed01f 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -90,6 +90,7 @@ enum { MASK_64_ADDRESSING_SUPPORT = 0x01000000, MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000, MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000, + MASK_CRYPTO_SUPPORT = 0x10000000, }; #define UFS_MASK(mask, offset) ((mask) << (offset)) @@ -143,6 +144,7 @@ enum { #define DEVICE_FATAL_ERROR 0x800 #define CONTROLLER_FATAL_ERROR 0x10000 #define SYSTEM_BUS_FATAL_ERROR 0x20000 +#define CRYPTO_ENGINE_FATAL_ERROR 0x40000 #define UFSHCD_UIC_HIBERN8_MASK (UIC_HIBERNATE_ENTER |\ UIC_HIBERNATE_EXIT) @@ -155,11 +157,13 @@ enum { #define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\ - SYSTEM_BUS_FATAL_ERROR) + SYSTEM_BUS_FATAL_ERROR |\ + CRYPTO_ENGINE_FATAL_ERROR) #define INT_FATAL_ERRORS (DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\ - SYSTEM_BUS_FATAL_ERROR) + SYSTEM_BUS_FATAL_ERROR |\ + CRYPTO_ENGINE_FATAL_ERROR) /* HCS - Host Controller Status 30h */ #define DEVICE_PRESENT 0x1 @@ -318,6 +322,61 @@ enum { INTERRUPT_MASK_ALL_VER_21 = 0x71FFF, }; +/* CCAP - Crypto Capability 100h */ +union ufs_crypto_capabilities { + __le32 reg_val; + struct { + u8 num_crypto_cap; + u8 config_count; + u8 reserved; + u8 config_array_ptr; + }; +}; + +enum ufs_crypto_key_size { + UFS_CRYPTO_KEY_SIZE_INVALID = 0x0, + UFS_CRYPTO_KEY_SIZE_128 = 0x1, + UFS_CRYPTO_KEY_SIZE_192 = 0x2, + UFS_CRYPTO_KEY_SIZE_256 = 0x3, + UFS_CRYPTO_KEY_SIZE_512 = 0x4, +}; + +enum ufs_crypto_alg { + UFS_CRYPTO_ALG_AES_XTS = 0x0, + UFS_CRYPTO_ALG_BITLOCKER_AES_CBC = 0x1, + UFS_CRYPTO_ALG_AES_ECB = 0x2, + UFS_CRYPTO_ALG_ESSIV_AES_CBC = 0x3, +}; + +/* x-CRYPTOCAP - Crypto Capability X */ +union ufs_crypto_cap_entry { + __le32 reg_val; + struct { + u8 algorithm_id; + u8 sdus_mask; /* Supported data unit size mask */ + u8 key_size; + u8 reserved; + }; +}; + +#define UFS_CRYPTO_CONFIGURATION_ENABLE (1 << 7) +#define UFS_CRYPTO_KEY_MAX_SIZE 64 +/* x-CRYPTOCFG - Crypto Configuration X */ +union ufs_crypto_cfg_entry { + __le32 reg_val[32]; + struct { + u8 crypto_key[UFS_CRYPTO_KEY_MAX_SIZE]; + u8 data_unit_size; + u8 crypto_cap_idx; + u8 reserved_1; + u8 config_enable; + u8 reserved_multi_host; + u8 reserved_2; + u8 vsb[2]; + u8 reserved_3[56]; + }; +}; + /* * Request Descriptor Definitions */ @@ -339,6 +398,7 @@ enum { UTP_NATIVE_UFS_COMMAND = 0x10000000, UTP_DEVICE_MANAGEMENT_FUNCTION = 0x20000000, UTP_REQ_DESC_INT_CMD = 0x01000000, + UTP_REQ_DESC_CRYPTO_ENABLE_CMD = 0x00800000, }; /* UTP Transfer Request Data Direction (DD) */ @@ -358,6 +418,9 @@ enum { OCS_PEER_COMM_FAILURE = 0x5, OCS_ABORTED = 0x6, OCS_FATAL_ERROR = 0x7, + OCS_DEVICE_FATAL_ERROR = 0x8, + OCS_INVALID_CRYPTO_CONFIG = 0x9, + OCS_GENERAL_CRYPTO_ERROR = 0xA, OCS_INVALID_COMMAND_STATUS = 0x0F, MASK_OCS = 0x0F, }; diff --git a/drivers/soc/imx/soc-imx-scu.c b/drivers/soc/imx/soc-imx-scu.c index 50831ebf126afcdc2ea26e5c2d1db98e05cd0afa..c68882eb80f778e93bf7b1e29cc18b8e06f44d7a 100644 --- a/drivers/soc/imx/soc-imx-scu.c +++ b/drivers/soc/imx/soc-imx-scu.c @@ -46,7 +46,7 @@ static ssize_t soc_uid_show(struct device *dev, hdr->func = IMX_SC_MISC_FUNC_UNIQUE_ID; hdr->size = 1; - ret = imx_scu_call_rpc(soc_ipc_handle, &msg, false); + ret = imx_scu_call_rpc(soc_ipc_handle, &msg, true); if (ret) { pr_err("%s: get soc uid failed, ret %d\n", __func__, ret); return ret; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a499a76453ee23b08dffd78ab8e0af7f8f7ca68f..1f9096f138771eb8069a2cfecd73ee175c6422c6 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -231,33 +231,30 @@ DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, static int ion_assign_heap_id(struct ion_heap *heap, struct ion_device *dev) { - int id_bit; - int start_bit, end_bit = -1; + int id_bit = -EINVAL; + int start_bit = -1, end_bit = -1; switch (heap->type) { case ION_HEAP_TYPE_SYSTEM: - id_bit = ffs(ION_HEAP_SYSTEM); + id_bit = __ffs(ION_HEAP_SYSTEM); break; case ION_HEAP_TYPE_SYSTEM_CONTIG: - id_bit = ffs(ION_HEAP_SYSTEM_CONTIG); + id_bit = __ffs(ION_HEAP_SYSTEM_CONTIG); break; case ION_HEAP_TYPE_CHUNK: - id_bit = ffs(ION_HEAP_CHUNK); + id_bit = __ffs(ION_HEAP_CHUNK); break; case ION_HEAP_TYPE_CARVEOUT: - id_bit = 0; - start_bit = ffs(ION_HEAP_CARVEOUT_START); - end_bit = ffs(ION_HEAP_CARVEOUT_END); + start_bit = __ffs(ION_HEAP_CARVEOUT_START); + end_bit = __ffs(ION_HEAP_CARVEOUT_END); break; case ION_HEAP_TYPE_DMA: - id_bit = 0; - start_bit = ffs(ION_HEAP_DMA_START); - end_bit = ffs(ION_HEAP_DMA_END); + start_bit = __ffs(ION_HEAP_DMA_START); + end_bit = __ffs(ION_HEAP_DMA_END); break; case ION_HEAP_TYPE_CUSTOM ... ION_HEAP_TYPE_MAX: - id_bit = 0; - start_bit = ffs(ION_HEAP_CUSTOM_START); - end_bit = ffs(ION_HEAP_CUSTOM_END); + start_bit = __ffs(ION_HEAP_CUSTOM_START); + end_bit = __ffs(ION_HEAP_CUSTOM_END); break; default: return -EINVAL; @@ -271,9 +268,9 @@ static int ion_assign_heap_id(struct ion_heap *heap, struct ion_device *dev) * If the heap hasn't picked an id by itself, then we assign it * one. */ - if (!id_bit) { + if (id_bit < 0) { if (heap->id) { - id_bit = ffs(heap->id); + id_bit = __ffs(heap->id); if (id_bit < start_bit || id_bit > end_bit) return -EINVAL; } else { @@ -284,9 +281,9 @@ static int ion_assign_heap_id(struct ion_heap *heap, struct ion_device *dev) } } - if (test_and_set_bit(id_bit - 1, dev->heap_ids)) + if (test_and_set_bit(id_bit, dev->heap_ids)) return -EEXIST; - heap->id = id_bit - 1; + heap->id = id_bit; dev->heap_cnt++; return 0; diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index eee1998c4b189179b6de81f2fa98717bb5395176..fac38c842ac50bce8f53441369f61fd8cd20a0bd 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -469,10 +469,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, /* Set the encryption - we only support wep */ if (is_wep) { if (sme->key) { - if (sme->key_idx >= NUM_WEPKEYS) { - err = -EINVAL; - goto exit; - } + if (sme->key_idx >= NUM_WEPKEYS) + return -EINVAL; result = prism2_domibset_uint32(wlandev, DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID, diff --git a/drivers/target/iscsi/cxgbit/cxgbit_cm.c b/drivers/target/iscsi/cxgbit/cxgbit_cm.c index c70caf4ea49012006c3a8ac754ff9e1c16399ec7..a2b5c796bbc4a5dfee4513bd93a6449e57d4dbc4 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_cm.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_cm.c @@ -1831,7 +1831,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb) while (credits) { struct sk_buff *p = cxgbit_sock_peek_wr(csk); - const u32 csum = (__force u32)p->csum; + u32 csum; if (unlikely(!p)) { pr_err("csk 0x%p,%u, cr %u,%u+%u, empty.\n", @@ -1840,6 +1840,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb) break; } + csum = (__force u32)p->csum; if (unlikely(credits < csum)) { pr_warn("csk 0x%p,%u, cr %u,%u+%u, < %u.\n", csk, csk->tid, diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 04bf2acd3800ded1e776c087f7e2145bf219553b..2d19f0e332b0157695c6e7e87fdc7a25ab3b59cd 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1074,27 +1074,6 @@ passthrough_parse_cdb(struct se_cmd *cmd, struct se_device *dev = cmd->se_dev; unsigned int size; - /* - * Clear a lun set in the cdb if the initiator talking to use spoke - * and old standards version, as we can't assume the underlying device - * won't choke up on it. - */ - switch (cdb[0]) { - case READ_10: /* SBC - RDProtect */ - case READ_12: /* SBC - RDProtect */ - case READ_16: /* SBC - RDProtect */ - case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */ - case VERIFY: /* SBC - VRProtect */ - case VERIFY_16: /* SBC - VRProtect */ - case WRITE_VERIFY: /* SBC - VRProtect */ - case WRITE_VERIFY_12: /* SBC - VRProtect */ - case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */ - break; - default: - cdb[1] &= 0x1f; /* clear logical unit number */ - break; - } - /* * For REPORT LUNS we always need to emulate the response, for everything * else, pass it up. diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 391f39776c6ab8c6205ef0a122079887e53220ea..6b9865c786ba3b146143624295592a19629cae3f 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -88,7 +88,7 @@ struct cpufreq_cooling_device { struct cpufreq_policy *policy; struct list_head node; struct time_in_idle *idle_time; - struct dev_pm_qos_request qos_req; + struct freq_qos_request qos_req; }; static DEFINE_IDA(cpufreq_ida); @@ -331,7 +331,7 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, cpufreq_cdev->cpufreq_state = state; - return dev_pm_qos_update_request(&cpufreq_cdev->qos_req, + return freq_qos_update_request(&cpufreq_cdev->qos_req, cpufreq_cdev->freq_table[state].frequency); } @@ -615,9 +615,9 @@ __cpufreq_cooling_register(struct device_node *np, cooling_ops = &cpufreq_cooling_ops; } - ret = dev_pm_qos_add_request(dev, &cpufreq_cdev->qos_req, - DEV_PM_QOS_MAX_FREQUENCY, - cpufreq_cdev->freq_table[0].frequency); + ret = freq_qos_add_request(&policy->constraints, + &cpufreq_cdev->qos_req, FREQ_QOS_MAX, + cpufreq_cdev->freq_table[0].frequency); if (ret < 0) { pr_err("%s: Failed to add freq constraint (%d)\n", __func__, ret); @@ -637,7 +637,7 @@ __cpufreq_cooling_register(struct device_node *np, return cdev; remove_qos_req: - dev_pm_qos_remove_request(&cpufreq_cdev->qos_req); + freq_qos_remove_request(&cpufreq_cdev->qos_req); remove_ida: ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); free_table: @@ -736,7 +736,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) mutex_unlock(&cooling_list_lock); thermal_cooling_device_unregister(cdev); - dev_pm_qos_remove_request(&cpufreq_cdev->qos_req); + freq_qos_remove_request(&cpufreq_cdev->qos_req); ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); kfree(cpufreq_cdev->idle_time); kfree(cpufreq_cdev->freq_table); diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c index 02c5aff58a7408d3509f020b18f5a5cd93eac6c6..8df89e9cd2542d05dff25fc377b08d30a9efe5c5 100644 --- a/drivers/tty/serial/8250/8250_men_mcb.c +++ b/drivers/tty/serial/8250/8250_men_mcb.c @@ -72,8 +72,8 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev, { struct serial_8250_men_mcb_data *data; struct resource *mem; - unsigned int num_ports; - unsigned int i; + int num_ports; + int i; void __iomem *membase; mem = mcb_get_resource(mdev, IORESOURCE_MEM); @@ -88,7 +88,7 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev, dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n", mdev->id, num_ports); - if (num_ports == 0 || num_ports > 4) { + if (num_ports <= 0 || num_ports > 4) { dev_err(&mdev->dev, "unexpected number of ports: %u\n", num_ports); return -ENODEV; @@ -133,7 +133,7 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev, static void serial_8250_men_mcb_remove(struct mcb_device *mdev) { - unsigned int num_ports, i; + int num_ports, i; struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev); if (!data) diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c index 1109dc5a4c39a959848a9bc2c0ac2552fda87da8..c2123ef8d8a3320f11f1fa3b7b0363dc3886cd86 100644 --- a/drivers/usb/cdns3/core.c +++ b/drivers/usb/cdns3/core.c @@ -166,7 +166,6 @@ static int cdns3_core_init_role(struct cdns3 *cdns) goto err; switch (cdns->dr_mode) { - case USB_DR_MODE_UNKNOWN: case USB_DR_MODE_OTG: ret = cdns3_hw_role_switch(cdns); if (ret) @@ -182,6 +181,9 @@ static int cdns3_core_init_role(struct cdns3 *cdns) if (ret) goto err; break; + default: + ret = -EINVAL; + goto err; } return ret; diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 2ca280f4c054124b48d0900c61fe9b47a131d9f6..4c1e755093039d0582ca30922d620009441aed0c 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -1145,6 +1145,14 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, request = cdns3_next_request(&priv_ep->pending_req_list); priv_req = to_cdns3_request(request); + trb = priv_ep->trb_pool + priv_ep->dequeue; + + /* Request was dequeued and TRB was changed to TRB_LINK. */ + if (TRB_FIELD_TO_TYPE(trb->control) == TRB_LINK) { + trace_cdns3_complete_trb(priv_ep, trb); + cdns3_move_deq_to_next_trb(priv_req); + } + /* Re-select endpoint. It could be changed by other CPU during * handling usb_gadget_giveback_request. */ @@ -2067,6 +2075,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep, struct usb_request *req, *req_temp; struct cdns3_request *priv_req; struct cdns3_trb *link_trb; + u8 req_on_hw_ring = 0; unsigned long flags; int ret = 0; @@ -2083,8 +2092,10 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep, list_for_each_entry_safe(req, req_temp, &priv_ep->pending_req_list, list) { - if (request == req) + if (request == req) { + req_on_hw_ring = 1; goto found; + } } list_for_each_entry_safe(req, req_temp, &priv_ep->deferred_req_list, @@ -2096,27 +2107,21 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep, goto not_found; found: - - if (priv_ep->wa1_trb == priv_req->trb) - cdns3_wa1_restore_cycle_bit(priv_ep); - link_trb = priv_req->trb; - cdns3_move_deq_to_next_trb(priv_req); - cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET); - - /* Update ring */ - request = cdns3_next_request(&priv_ep->deferred_req_list); - if (request) { - priv_req = to_cdns3_request(request); + /* Update ring only if removed request is on pending_req_list list */ + if (req_on_hw_ring) { link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma + (priv_req->start_trb * TRB_SIZE)); link_trb->control = (link_trb->control & TRB_CYCLE) | - TRB_TYPE(TRB_LINK) | TRB_CHAIN | TRB_TOGGLE; - } else { - priv_ep->flags |= EP_UPDATE_EP_TRBADDR; + TRB_TYPE(TRB_LINK) | TRB_CHAIN; + + if (priv_ep->wa1_trb == priv_req->trb) + cdns3_wa1_restore_cycle_bit(priv_ep); } + cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET); + not_found: spin_unlock_irqrestore(&priv_dev->lock, flags); return ret; @@ -2324,8 +2329,6 @@ static void cdns3_gadget_config(struct cdns3_device *priv_dev) writel(USB_CONF_CLK2OFFDS | USB_CONF_L1DS, ®s->usb_conf); cdns3_configure_dmult(priv_dev, NULL); - - cdns3_gadget_pullup(&priv_dev->gadget, 1); } /** @@ -2340,9 +2343,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget, { struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); unsigned long flags; + enum usb_device_speed max_speed = driver->max_speed; spin_lock_irqsave(&priv_dev->lock, flags); priv_dev->gadget_driver = driver; + + /* limit speed if necessary */ + max_speed = min(driver->max_speed, gadget->max_speed); + + switch (max_speed) { + case USB_SPEED_FULL: + writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf); + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf); + break; + case USB_SPEED_HIGH: + writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf); + break; + case USB_SPEED_SUPER: + break; + default: + dev_err(priv_dev->dev, + "invalid maximum_speed parameter %d\n", + max_speed); + /* fall through */ + case USB_SPEED_UNKNOWN: + /* default to superspeed */ + max_speed = USB_SPEED_SUPER; + break; + } + cdns3_gadget_config(priv_dev); spin_unlock_irqrestore(&priv_dev->lock, flags); return 0; @@ -2376,6 +2405,8 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget) writel(EP_CMD_EPRST, &priv_dev->regs->ep_cmd); readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val, !(val & EP_CMD_EPRST), 1, 100); + + priv_ep->flags &= ~EP_CLAIMED; } /* disable interrupt for device */ @@ -2570,12 +2601,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns) /* Check the maximum_speed parameter */ switch (max_speed) { case USB_SPEED_FULL: - writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf); - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf); - break; case USB_SPEED_HIGH: - writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf); - break; case USB_SPEED_SUPER: break; default: @@ -2708,8 +2734,6 @@ static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup) /* disable interrupt for device */ writel(0, &priv_dev->regs->usb_ien); - cdns3_gadget_pullup(&priv_dev->gadget, 0); - return 0; } diff --git a/drivers/usb/cdns3/host-export.h b/drivers/usb/cdns3/host-export.h index b498a170b7e881f3e98f6ba860db27cb928f4fde..ae11810f882618c052e4d4315315380fa74e3f9e 100644 --- a/drivers/usb/cdns3/host-export.h +++ b/drivers/usb/cdns3/host-export.h @@ -12,7 +12,6 @@ #ifdef CONFIG_USB_CDNS3_HOST int cdns3_host_init(struct cdns3 *cdns); -void cdns3_host_exit(struct cdns3 *cdns); #else diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c index 2733a8f71fcd6572634899324e5152538e00299d..ad788bf3fe4f6f8e9ac1865fd3d6c6ca518ba341 100644 --- a/drivers/usb/cdns3/host.c +++ b/drivers/usb/cdns3/host.c @@ -12,6 +12,7 @@ #include #include "core.h" #include "drd.h" +#include "host-export.h" static int __cdns3_host_init(struct cdns3 *cdns) { diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index fb8bd60c83f487d67c1b1479dc2d1cf86d1a8bed..0d8e3f3804a3f87e8d8a29442f2db0a50c621ac7 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -445,6 +445,7 @@ static void usblp_cleanup(struct usblp *usblp) kfree(usblp->readbuf); kfree(usblp->device_id_string); kfree(usblp->statusbuf); + usb_put_intf(usblp->intf); kfree(usblp); } @@ -1113,7 +1114,7 @@ static int usblp_probe(struct usb_interface *intf, init_waitqueue_head(&usblp->wwait); init_usb_anchor(&usblp->urbs); usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - usblp->intf = intf; + usblp->intf = usb_get_intf(intf); /* Malloc device ID string buffer to the largest expected length, * since we can re-query it on an ioctl and a dynamic string @@ -1198,6 +1199,7 @@ static int usblp_probe(struct usb_interface *intf, kfree(usblp->readbuf); kfree(usblp->statusbuf); kfree(usblp->device_id_string); + usb_put_intf(usblp->intf); kfree(usblp); abort_ret: return retval; diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 151a74a54386226c1f0fc6a134556151a5bd28dc..1ac1095bfeac8448ff7fae2179a033fb558bb6ff 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -348,6 +348,11 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, /* Validate the wMaxPacketSize field */ maxp = usb_endpoint_maxp(&endpoint->desc); + if (maxp == 0) { + dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n", + cfgno, inum, asnum, d->bEndpointAddress); + goto skip_to_next_endpoint_or_interface_descriptor; + } /* Find the highest legal maxpacket size for this endpoint */ i = 0; /* additional transactions per microframe */ diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 733c1c37443ccc4060ae5dba5e2933f8bd0f8cb4..70963a21052800ce4cac4f5b2637f648ffbd463c 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -102,6 +102,7 @@ config USB_DWC3_MESON_G12A depends on ARCH_MESON || COMPILE_TEST default USB_DWC3 select USB_ROLE_SWITCH + select REGMAP_MMIO help Support USB2/3 functionality in Amlogic G12A platforms. Say 'Y' or 'M' if you have one such device. diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 1abce68348e423ed613840e5e7f3b8fc71dcd55a..50a2c406df1092cd4bcad4e963a81c41d59f9418 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -330,8 +330,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); dft = reg & DWC3_GFLADJ_30MHZ_MASK; - if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj, - "request value same as default, ignoring\n")) { + if (dft != dwc->fladj) { reg &= ~DWC3_GFLADJ_30MHZ_MASK; reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 5e8e18222f922c00a646063b91599be7100feb41..023f0357efd77eae3182aaf596120b8a8847fa8b 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -258,7 +258,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) ret = platform_device_add_properties(dwc->dwc3, p); if (ret < 0) - return ret; + goto err; ret = dwc3_pci_quirks(dwc); if (ret) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8d07c59a44756b6571b5e67ae87dcc15b2e37f59..77952ea656fd28ba66ce5e168754b9cb14f8e2ee 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -824,6 +824,12 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) dwc3_gadget_giveback(dep, req, -ESHUTDOWN); } + while (!list_empty(&dep->cancelled_list)) { + req = next_request(&dep->cancelled_list); + + dwc3_gadget_giveback(dep, req, -ESHUTDOWN); + } + if (dep->number == 1 && dwc->ep0state != EP0_SETUP_PHASE) { unsigned int dir; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index d516e8d6cd7f939bd6c7bad09ded75bd40353d80..5ec54b69c29c58b1432b3c42b9d9bc58238db1d7 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2170,14 +2170,18 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev) usb_ep_dequeue(cdev->gadget->ep0, cdev->os_desc_req); kfree(cdev->os_desc_req->buf); + cdev->os_desc_req->buf = NULL; usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req); + cdev->os_desc_req = NULL; } if (cdev->req) { if (cdev->setup_pending) usb_ep_dequeue(cdev->gadget->ep0, cdev->req); kfree(cdev->req->buf); + cdev->req->buf = NULL; usb_ep_free_request(cdev->gadget->ep0, cdev->req); + cdev->req = NULL; } cdev->next_string_id = 0; device_remove_file(&cdev->gadget->dev, &dev_attr_suspended); diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index b0148a44930657445182b49cb62a62a066759b05..469c6fe1d747d4f95b5512ba054e7db0007dffde 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -86,6 +86,8 @@ struct gadget_info { bool use_os_desc; char b_vendor_code; char qw_sign[OS_STRING_QW_SIGN_LEN]; + spinlock_t spinlock; + bool unbind; #ifdef CONFIG_USB_CONFIGFS_UEVENT bool connected; bool sw_connected; @@ -1275,6 +1277,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget, int ret; /* the gi->lock is hold by the caller */ + gi->unbind = 0; cdev->gadget = gadget; set_gadget_data(gadget, cdev); ret = composite_dev_prepare(composite, cdev); @@ -1461,19 +1464,118 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) { struct usb_composite_dev *cdev; struct gadget_info *gi; + unsigned long flags; /* the gi->lock is hold by the caller */ cdev = get_gadget_data(gadget); gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + gi->unbind = 1; + spin_unlock_irqrestore(&gi->spinlock, flags); kfree(otg_desc[0]); otg_desc[0] = NULL; purge_configs_funcs(gi); composite_dev_cleanup(cdev); usb_ep_autoconfig_reset(cdev->gadget); + spin_lock_irqsave(&gi->spinlock, flags); cdev->gadget = NULL; set_gadget_data(gadget, NULL); + spin_unlock_irqrestore(&gi->spinlock, flags); +} + +#ifndef CONFIG_USB_CONFIGFS_UEVENT +static int configfs_composite_setup(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + int ret; + + cdev = get_gadget_data(gadget); + if (!cdev) + return 0; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return 0; + } + + ret = composite_setup(gadget, ctrl); + spin_unlock_irqrestore(&gi->spinlock, flags); + return ret; +} + +static void configfs_composite_disconnect(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + + cdev = get_gadget_data(gadget); + if (!cdev) + return; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return; + } + + composite_disconnect(gadget); + spin_unlock_irqrestore(&gi->spinlock, flags); +} +#endif + +static void configfs_composite_suspend(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + + cdev = get_gadget_data(gadget); + if (!cdev) + return; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return; + } + + composite_suspend(gadget); + spin_unlock_irqrestore(&gi->spinlock, flags); +} + +static void configfs_composite_resume(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + + cdev = get_gadget_data(gadget); + if (!cdev) + return; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return; + } + + composite_resume(gadget); + spin_unlock_irqrestore(&gi->spinlock, flags); } #ifdef CONFIG_USB_CONFIGFS_UEVENT @@ -1552,17 +1654,18 @@ static void android_disconnect(struct usb_gadget *gadget) static const struct usb_gadget_driver configfs_driver_template = { .bind = configfs_composite_bind, .unbind = configfs_composite_unbind, + #ifdef CONFIG_USB_CONFIGFS_UEVENT .setup = android_setup, .reset = android_disconnect, .disconnect = android_disconnect, #else - .setup = composite_setup, - .reset = composite_disconnect, - .disconnect = composite_disconnect, + .setup = configfs_composite_setup, + .reset = configfs_composite_disconnect, + .disconnect = configfs_composite_disconnect, #endif - .suspend = composite_suspend, - .resume = composite_resume, + .suspend = configfs_composite_suspend, + .resume = configfs_composite_resume, .max_speed = USB_SPEED_SUPER, .driver = { diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 86ffc83078647b2ba1dfbfc6e796489af15c9192..1d0d8952a74bfa4a786c6966fff1bbcbc66438a7 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -449,9 +449,11 @@ static void submit_request(struct usba_ep *ep, struct usba_request *req) next_fifo_transaction(ep, req); if (req->last_transaction) { usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); - usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); + if (ep_is_control(ep)) + usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); } else { - usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); + if (ep_is_control(ep)) + usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); } } diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 92af8dc98c3dcd1d5f0c474293916636049d8332..51fa614b40794310e3216f5b086442d969b5b3be 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -98,6 +98,17 @@ int usb_ep_enable(struct usb_ep *ep) if (ep->enabled) goto out; + /* UDC drivers can't handle endpoints with maxpacket size 0 */ + if (usb_endpoint_maxp(ep->desc) == 0) { + /* + * We should log an error message here, but we can't call + * dev_err() because there's no way to find the gadget + * given only ep. + */ + ret = -EINVAL; + goto out; + } + ret = ep->ops->enable(ep, ep->desc); if (ret) goto out; diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index 20141c3096f68ab4a2f51762dc0617715e473633..9a05863b28768a3e8fea85b376935baf961d36e9 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -2576,7 +2576,7 @@ static int fsl_udc_remove(struct platform_device *pdev) dma_pool_destroy(udc_controller->td_pool); free_irq(udc_controller->irq, udc_controller); iounmap(dr_regs); - if (pdata->operating_mode == FSL_USB2_DR_DEVICE) + if (res && (pdata->operating_mode == FSL_USB2_DR_DEVICE)) release_mem_region(res->start, resource_size(res)); /* free udc --wait for the release() finished */ diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 2b1f3cc7819bfb0b49a118a545486efaec024c2c..bf6c81e2f8cccf9e2d6644d728141e7991749de9 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -1177,11 +1177,11 @@ static void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes) tmp = readl(USBD_RXDATA(udc->udp_baseaddr)); bl = bytes - n; - if (bl > 3) - bl = 3; + if (bl > 4) + bl = 4; for (i = 0; i < bl; i++) - data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF); + data[n + i] = (u8) ((tmp >> (i * 8)) & 0xFF); } break; diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index e098f16c01cb5dedef6e4084c33a7ec39f43acdc..33703140233aa592001eaeb64298b5f119da9b0a 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -1544,10 +1544,10 @@ static void usb3_set_device_address(struct renesas_usb3 *usb3, u16 addr) static bool usb3_std_req_set_address(struct renesas_usb3 *usb3, struct usb_ctrlrequest *ctrl) { - if (ctrl->wValue >= 128) + if (le16_to_cpu(ctrl->wValue) >= 128) return true; /* stall */ - usb3_set_device_address(usb3, ctrl->wValue); + usb3_set_device_address(usb3, le16_to_cpu(ctrl->wValue)); usb3_set_p0_con_for_no_data(usb3); return false; @@ -1582,6 +1582,7 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3, struct renesas_usb3_ep *usb3_ep; int num; u16 status = 0; + __le16 tx_data; switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: @@ -1604,10 +1605,10 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3, } if (!stall) { - status = cpu_to_le16(status); + tx_data = cpu_to_le16(status); dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n", usb_req_to_usb3_req(usb3->ep0_req)); - usb3_pipe0_internal_xfer(usb3, &status, sizeof(status), + usb3_pipe0_internal_xfer(usb3, &tx_data, sizeof(tx_data), usb3_pipe0_get_status_completion); } @@ -1772,7 +1773,7 @@ static bool usb3_std_req_set_sel(struct renesas_usb3 *usb3, static bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3, struct usb_ctrlrequest *ctrl) { - if (ctrl->wValue > 0) + if (le16_to_cpu(ctrl->wValue) > 0) usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON); else usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON); diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index 7ba6afc7ef230ed69da605ce48e31cac4783a709..76c3f29562d2b9d2e3263f3d3dc1b45b92728140 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -202,10 +202,10 @@ static void xhci_ring_dump_segment(struct seq_file *s, trb = &seg->trbs[i]; dma = seg->dma + i * sizeof(*trb); seq_printf(s, "%pad: %s\n", &dma, - xhci_decode_trb(trb->generic.field[0], - trb->generic.field[1], - trb->generic.field[2], - trb->generic.field[3])); + xhci_decode_trb(le32_to_cpu(trb->generic.field[0]), + le32_to_cpu(trb->generic.field[1]), + le32_to_cpu(trb->generic.field[2]), + le32_to_cpu(trb->generic.field[3]))); } } @@ -263,10 +263,10 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused) xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus)); slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx); seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma, - xhci_decode_slot_context(slot_ctx->dev_info, - slot_ctx->dev_info2, - slot_ctx->tt_info, - slot_ctx->dev_state)); + xhci_decode_slot_context(le32_to_cpu(slot_ctx->dev_info), + le32_to_cpu(slot_ctx->dev_info2), + le32_to_cpu(slot_ctx->tt_info), + le32_to_cpu(slot_ctx->dev_state))); return 0; } @@ -286,10 +286,10 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused) ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, dci); dma = dev->out_ctx->dma + dci * CTX_SIZE(xhci->hcc_params); seq_printf(s, "%pad: %s\n", &dma, - xhci_decode_ep_context(ep_ctx->ep_info, - ep_ctx->ep_info2, - ep_ctx->deq, - ep_ctx->tx_info)); + xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info), + le32_to_cpu(ep_ctx->ep_info2), + le64_to_cpu(ep_ctx->deq), + le32_to_cpu(ep_ctx->tx_info))); } return 0; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 85ceb43e34056097fb63c8391a05c67a1acf80ed..e7aab31fd9a5a38b260e498947de7808259098d0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3330,6 +3330,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (xhci_urb_suitable_for_idt(urb)) { memcpy(&send_addr, urb->transfer_buffer, trb_buff_len); + le64_to_cpus(&send_addr); field |= TRB_IDT; } } @@ -3475,6 +3476,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (xhci_urb_suitable_for_idt(urb)) { memcpy(&addr, urb->transfer_buffer, urb->transfer_buffer_length); + le64_to_cpus(&addr); field |= TRB_IDT; } else { addr = (u64) urb->transfer_dma; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 517ec3206f6eb0681075c75c2c432b27350b51df..6c17e3fe181a2113464d4120984ad1125405888c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3071,6 +3071,48 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index, } } +static void xhci_endpoint_disable(struct usb_hcd *hcd, + struct usb_host_endpoint *host_ep) +{ + struct xhci_hcd *xhci; + struct xhci_virt_device *vdev; + struct xhci_virt_ep *ep; + struct usb_device *udev; + unsigned long flags; + unsigned int ep_index; + + xhci = hcd_to_xhci(hcd); +rescan: + spin_lock_irqsave(&xhci->lock, flags); + + udev = (struct usb_device *)host_ep->hcpriv; + if (!udev || !udev->slot_id) + goto done; + + vdev = xhci->devs[udev->slot_id]; + if (!vdev) + goto done; + + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = &vdev->eps[ep_index]; + if (!ep) + goto done; + + /* wait for hub_tt_work to finish clearing hub TT */ + if (ep->ep_state & EP_CLEARING_TT) { + spin_unlock_irqrestore(&xhci->lock, flags); + schedule_timeout_uninterruptible(1); + goto rescan; + } + + if (ep->ep_state) + xhci_dbg(xhci, "endpoint disable with ep_state 0x%x\n", + ep->ep_state); +done: + host_ep->hcpriv = NULL; + spin_unlock_irqrestore(&xhci->lock, flags); +} + /* * Called after usb core issues a clear halt control message. * The host side of the halt should already be cleared by a reset endpoint @@ -5238,20 +5280,13 @@ static void xhci_clear_tt_buffer_complete(struct usb_hcd *hcd, unsigned int ep_index; unsigned long flags; - /* - * udev might be NULL if tt buffer is cleared during a failed device - * enumeration due to a halted control endpoint. Usb core might - * have allocated a new udev for the next enumeration attempt. - */ - xhci = hcd_to_xhci(hcd); + + spin_lock_irqsave(&xhci->lock, flags); udev = (struct usb_device *)ep->hcpriv; - if (!udev) - return; slot_id = udev->slot_id; ep_index = xhci_get_endpoint_index(&ep->desc); - spin_lock_irqsave(&xhci->lock, flags); xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_CLEARING_TT; xhci_ring_doorbell_for_active_rings(xhci, slot_id, ep_index); spin_unlock_irqrestore(&xhci->lock, flags); @@ -5288,6 +5323,7 @@ static const struct hc_driver xhci_hc_driver = { .free_streams = xhci_free_streams, .add_endpoint = xhci_add_endpoint, .drop_endpoint = xhci_drop_endpoint, + .endpoint_disable = xhci_endpoint_disable, .endpoint_reset = xhci_endpoint_reset, .check_bandwidth = xhci_check_bandwidth, .reset_bandwidth = xhci_reset_bandwidth, diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index f3108d85e768086293954e8a869b79d4a75901e2..8f86b4ebca898b32e572cba6006ca01ab414b2ea 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -380,10 +380,7 @@ static int ld_usb_release(struct inode *inode, struct file *file) goto exit; } - if (mutex_lock_interruptible(&dev->mutex)) { - retval = -ERESTARTSYS; - goto exit; - } + mutex_lock(&dev->mutex); if (dev->open_count != 1) { retval = -ENODEV; @@ -467,7 +464,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, /* wait for data */ spin_lock_irq(&dev->rbsl); - if (dev->ring_head == dev->ring_tail) { + while (dev->ring_head == dev->ring_tail) { dev->interrupt_in_done = 0; spin_unlock_irq(&dev->rbsl); if (file->f_flags & O_NONBLOCK) { @@ -477,15 +474,20 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); if (retval < 0) goto unlock_exit; - } else { - spin_unlock_irq(&dev->rbsl); + + spin_lock_irq(&dev->rbsl); } + spin_unlock_irq(&dev->rbsl); /* actual_buffer contains actual_length + interrupt_in_buffer */ actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_tail * (sizeof(size_t)+dev->interrupt_in_endpoint_size)); + if (*actual_buffer > dev->interrupt_in_endpoint_size) { + retval = -EIO; + goto unlock_exit; + } bytes_to_read = min(count, *actual_buffer); if (bytes_to_read < *actual_buffer) - dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n", + dev_warn(&dev->intf->dev, "Read buffer overflow, %zu bytes dropped\n", *actual_buffer-bytes_to_read); /* copy one interrupt_in_buffer from ring_buffer into userspace */ @@ -493,11 +495,11 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, retval = -EFAULT; goto unlock_exit; } - dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; - retval = bytes_to_read; spin_lock_irq(&dev->rbsl); + dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; + if (dev->buffer_overflow) { dev->buffer_overflow = 0; spin_unlock_irq(&dev->rbsl); @@ -560,8 +562,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, /* write the data into interrupt_out_buffer from userspace */ bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); if (bytes_to_write < count) - dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n", count-bytes_to_write); - dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", + dev_warn(&dev->intf->dev, "Write buffer overflow, %zu bytes dropped\n", + count - bytes_to_write); + dev_dbg(&dev->intf->dev, "%s: count = %zu, bytes_to_write = %zu\n", __func__, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { @@ -578,7 +581,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, 1 << 8, 0, dev->interrupt_out_buffer, bytes_to_write, - USB_CTRL_SET_TIMEOUT * HZ); + USB_CTRL_SET_TIMEOUT); if (retval < 0) dev_err(&dev->intf->dev, "Couldn't submit HID_REQ_SET_REPORT %d\n", @@ -693,10 +696,9 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); - dev->ring_buffer = - kmalloc_array(ring_buffer_size, - sizeof(size_t) + dev->interrupt_in_endpoint_size, - GFP_KERNEL); + dev->ring_buffer = kcalloc(ring_buffer_size, + sizeof(size_t) + dev->interrupt_in_endpoint_size, + GFP_KERNEL); if (!dev->ring_buffer) goto error; dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 9d4c52a7ebe02254d32cdb13d1f6107790d6d759..23061f1526b4e03be818de50add926e982187ae2 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -419,10 +419,7 @@ static int tower_release (struct inode *inode, struct file *file) goto exit; } - if (mutex_lock_interruptible(&dev->lock)) { - retval = -ERESTARTSYS; - goto exit; - } + mutex_lock(&dev->lock); if (dev->open_count != 1) { dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n", @@ -881,7 +878,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device get_version_reply, sizeof(*get_version_reply), 1000); - if (result < sizeof(*get_version_reply)) { + if (result != sizeof(*get_version_reply)) { if (result >= 0) result = -EIO; dev_err(idev, "get version request failed: %d\n", result); diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index c3d5c1206eec808bb96d54ef5cc713219c39c93e..9dd02160cca97e9242aac125d104df80cd72e3e3 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -16,6 +16,7 @@ #include #include "mtu3.h" +#include "mtu3_dr.h" #include "mtu3_debug.h" #include "mtu3_trace.h" diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 4c3de777ef6cf691abd606d0b98081c6f10143ce..a3c30b609433bacca844f3d0c0c174c6301e0d51 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -162,17 +162,17 @@ void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) req->bRequest = (val >> 8) & 0xFF; req->bRequestType = (val >> 0) & 0xFF; - req->wValue = usbhs_read(priv, USBVAL); - req->wIndex = usbhs_read(priv, USBINDX); - req->wLength = usbhs_read(priv, USBLENG); + req->wValue = cpu_to_le16(usbhs_read(priv, USBVAL)); + req->wIndex = cpu_to_le16(usbhs_read(priv, USBINDX)); + req->wLength = cpu_to_le16(usbhs_read(priv, USBLENG)); } void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) { usbhs_write(priv, USBREQ, (req->bRequest << 8) | req->bRequestType); - usbhs_write(priv, USBVAL, req->wValue); - usbhs_write(priv, USBINDX, req->wIndex); - usbhs_write(priv, USBLENG, req->wLength); + usbhs_write(priv, USBVAL, le16_to_cpu(req->wValue)); + usbhs_write(priv, USBINDX, le16_to_cpu(req->wIndex)); + usbhs_write(priv, USBLENG, le16_to_cpu(req->wLength)); usbhs_bset(priv, DCPCTR, SUREQ, SUREQ); } diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index e5ef56991dbac3a9607575ca7414e5c24bf11320..cd38d74b322320db3c9607f4ab30758d701949be 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -265,7 +265,7 @@ static int usbhsg_recip_handler_std_set_device(struct usbhs_priv *priv, case USB_DEVICE_TEST_MODE: usbhsg_recip_handler_std_control_done(priv, uep, ctrl); udelay(100); - usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex >> 8)); + usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex) >> 8); break; default: usbhsg_recip_handler_std_control_done(priv, uep, ctrl); @@ -315,7 +315,7 @@ static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv, struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); struct device *dev = usbhsg_gpriv_to_dev(gpriv); struct usb_request *req; - unsigned short *buf; + __le16 *buf; /* alloc new usb_request for recip */ req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC); diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index dd0ad67aa71e619907afdab6dc142a4335684e51..ef23acc9b9ce4bc8fe8ccb8197b42f69928a87b3 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -776,7 +776,6 @@ static void ti_close(struct usb_serial_port *port) struct ti_port *tport; int port_number; int status; - int do_unlock; unsigned long flags; tdev = usb_get_serial_data(port->serial); @@ -800,16 +799,13 @@ static void ti_close(struct usb_serial_port *port) "%s - cannot send close port command, %d\n" , __func__, status); - /* if mutex_lock is interrupted, continue anyway */ - do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock); - --tport->tp_tdev->td_open_port_count; - if (tport->tp_tdev->td_open_port_count <= 0) { + mutex_lock(&tdev->td_open_close_lock); + --tdev->td_open_port_count; + if (tdev->td_open_port_count == 0) { /* last port is closed, shut down interrupt urb */ usb_kill_urb(port->serial->port[0]->interrupt_in_urb); - tport->tp_tdev->td_open_port_count = 0; } - if (do_unlock) - mutex_unlock(&tdev->td_open_close_lock); + mutex_unlock(&tdev->td_open_close_lock); } diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 79314d8c94a446b9378aa7d5ebcb9a533e31cf1e..ca3bd58f2025a9957742970122cacd997ba67085 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -559,6 +559,10 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, command_port = port->serial->port[COMMAND_PORT]; command_info = usb_get_serial_port_data(command_port); + + if (command_port->bulk_out_size < datasize + 1) + return -EIO; + mutex_lock(&command_info->mutex); command_info->command_finished = false; @@ -632,6 +636,7 @@ static void firm_setup_port(struct tty_struct *tty) struct device *dev = &port->dev; struct whiteheat_port_settings port_settings; unsigned int cflag = tty->termios.c_cflag; + speed_t baud; port_settings.port = port->port_number + 1; @@ -692,11 +697,13 @@ static void firm_setup_port(struct tty_struct *tty) dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff); /* get the baud rate wanted */ - port_settings.baud = tty_get_baud_rate(tty); - dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud); + baud = tty_get_baud_rate(tty); + port_settings.baud = cpu_to_le32(baud); + dev_dbg(dev, "%s - baud rate = %u\n", __func__, baud); /* fixme: should set validated settings */ - tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud); + tty_encode_baud_rate(tty, baud, baud); + /* handle any settings that aren't specified in the tty structure */ port_settings.lloop = 0; diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h index 00398149cd8ddcf0985dd363d24d66415196cdd8..269e727a92f9c5bbe7c2825d988c06f0e640491c 100644 --- a/drivers/usb/serial/whiteheat.h +++ b/drivers/usb/serial/whiteheat.h @@ -87,7 +87,7 @@ struct whiteheat_simple { struct whiteheat_port_settings { __u8 port; /* port number (1 to N) */ - __u32 baud; /* any value 7 - 460800, firmware calculates + __le32 baud; /* any value 7 - 460800, firmware calculates best fit; arrives little endian */ __u8 bits; /* 5, 6, 7, or 8 */ __u8 stop; /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */ diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 6737fab9495949c0187364cfce1e7469687da9fa..54a3c8195c969785a6ab2a359a2787f321cce553 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -68,7 +68,6 @@ static const char* host_info(struct Scsi_Host *host) static int slave_alloc (struct scsi_device *sdev) { struct us_data *us = host_to_us(sdev->host); - int maxp; /* * Set the INQUIRY transfer length to 36. We don't use any of @@ -77,15 +76,6 @@ static int slave_alloc (struct scsi_device *sdev) */ sdev->inquiry_len = 36; - /* - * USB has unusual scatter-gather requirements: the length of each - * scatterlist element except the last must be divisible by the - * Bulk maxpacket value. Fortunately this value is always a - * power of 2. Inform the block layer about this requirement. - */ - maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0); - blk_queue_virt_boundary(sdev->request_queue, maxp - 1); - /* * Some host controllers may have alignment requirements. * We'll play it safe by requiring 512-byte alignment always. diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 047c5922618f81d014e5f62c67249763492f609c..0d044d59317edb2f16da69f32644ecb28c6c2161 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -789,29 +789,9 @@ static int uas_slave_alloc(struct scsi_device *sdev) { struct uas_dev_info *devinfo = (struct uas_dev_info *)sdev->host->hostdata; - int maxp; sdev->hostdata = devinfo; - /* - * We have two requirements here. We must satisfy the requirements - * of the physical HC and the demands of the protocol, as we - * definitely want no additional memory allocation in this path - * ruling out using bounce buffers. - * - * For a transmission on USB to continue we must never send - * a package that is smaller than maxpacket. Hence the length of each - * scatterlist element except the last must be divisible by the - * Bulk maxpacket value. - * If the HC does not ensure that through SG, - * the upper layer must do that. We must assume nothing - * about the capabilities off the HC, so we use the most - * pessimistic requirement. - */ - - maxp = usb_maxpacket(devinfo->udev, devinfo->data_in_pipe, 0); - blk_queue_virt_boundary(sdev->request_queue, maxp - 1); - /* * The protocol has no requirements on alignment in the strict sense. * Controllers may or may not have alignment restrictions. diff --git a/drivers/usb/usbip/vhci_tx.c b/drivers/usb/usbip/vhci_tx.c index c3803785f6eff23a74c2225cd696a7a69ea1a757..0ae40a13a9fea89650c4200a359530dd7c954281 100644 --- a/drivers/usb/usbip/vhci_tx.c +++ b/drivers/usb/usbip/vhci_tx.c @@ -147,7 +147,10 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) } kfree(iov); + /* This is only for isochronous case */ kfree(iso_buffer); + iso_buffer = NULL; + usbip_dbg_vhci_tx("send txdata\n"); total_size += txsize; diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 96fddc1dafc3c4dffd62bf98df51e48a0598febc..d864277ea16f31627ca776769297788995840400 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -1658,7 +1658,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, struct bus_type *bus = NULL; int ret; bool resv_msi, msi_remap; - phys_addr_t resv_msi_base; + phys_addr_t resv_msi_base = 0; struct iommu_domain_geometry geo; LIST_HEAD(iova_copy); LIST_HEAD(group_resv_regions); diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 7804869c6a31398ffbcc9cd1c5786b76f1f54274..056308008288c80dc14efbf6c437cbc6940129dd 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -161,6 +161,7 @@ static int vhost_test_release(struct inode *inode, struct file *f) vhost_test_stop(n, &private); vhost_test_flush(n); + vhost_dev_stop(&n->dev); vhost_dev_cleanup(&n->dev); /* We do an extra flush before freeing memory, * since jobs can re-queue themselves. */ @@ -237,6 +238,7 @@ static long vhost_test_reset_owner(struct vhost_test *n) } vhost_test_stop(n, &priv); vhost_test_flush(n); + vhost_dev_stop(&n->dev); vhost_dev_reset_owner(&n->dev, umem); done: mutex_unlock(&n->dev.mutex); diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index 08ad0d1f04766fe10b8a5829628983ec09f0b561..a0a2d74967ef57eb72f73a3bb5367177421ed2d6 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -852,6 +852,12 @@ static inline int xfer_kern(void *src, void *dst, size_t len) return 0; } +static inline int kern_xfer(void *dst, void *src, size_t len) +{ + memcpy(dst, src, len); + return 0; +} + /** * vringh_init_kern - initialize a vringh for a kernelspace vring. * @vrh: the vringh to initialize. @@ -958,7 +964,7 @@ EXPORT_SYMBOL(vringh_iov_pull_kern); ssize_t vringh_iov_push_kern(struct vringh_kiov *wiov, const void *src, size_t len) { - return vringh_iov_xfer(wiov, (void *)src, len, xfer_kern); + return vringh_iov_xfer(wiov, (void *)src, len, kern_xfer); } EXPORT_SYMBOL(vringh_iov_push_kern); diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c index 5ae529671b3d34b33813ec62bce0931d04c5f359..c68134c5a2e6089cb189eeb7b47d355f030276ff 100644 --- a/drivers/virtio/virtio_input.c +++ b/drivers/virtio/virtio_input.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -164,6 +165,12 @@ static void virtinput_cfg_abs(struct virtio_input *vi, int abs) virtio_cread(vi->vdev, struct virtio_input_config, u.abs.flat, &fl); input_set_abs_params(vi->idev, abs, mi, ma, fu, fl); input_abs_set_res(vi->idev, abs, re); + if (abs == ABS_MT_TRACKING_ID) + input_mt_init_slots(vi->idev, + ma, /* input max finger */ + INPUT_MT_DIRECT + | INPUT_MT_DROP_UNUSED + | INPUT_MT_TRACK); } static int virtinput_init_vqs(struct virtio_input *vi) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index bdc08244a648dbf0ee58fe8b9dc4e5e36c15dcb8..a8041e451e9ec6ba9982069477520d5df00386c2 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -1499,9 +1499,6 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq) * counter first before updating event flags. */ virtio_wmb(vq->weak_barriers); - } else { - used_idx = vq->last_used_idx; - wrap_counter = vq->packed.used_wrap_counter; } if (vq->packed.event_flags_shadow == VRING_PACKED_EVENT_FLAG_DISABLE) { @@ -1518,7 +1515,9 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq) */ virtio_mb(vq->weak_barriers); - if (is_used_desc_packed(vq, used_idx, wrap_counter)) { + if (is_used_desc_packed(vq, + vq->last_used_idx, + vq->packed.used_wrap_counter)) { END_USE(vq); return false; } diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c index 69a626b0e59420443b3972426c2d8be19714589c..c57c71b7d53dbab128c27bfdaadc4ac218469eb2 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c @@ -775,7 +775,7 @@ static int pvcalls_back_poll(struct xenbus_device *dev, mappass->reqcopy = *req; icsk = inet_csk(mappass->sock->sk); queue = &icsk->icsk_accept_queue; - data = queue->rskq_accept_head != NULL; + data = READ_ONCE(queue->rskq_accept_head) != NULL; if (data) { mappass->reqcopy.cmd = 0; ret = 0; diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index bf7e3f23bba745528f863066c4d0be5224d8d2e1..670700cb1110692c2fc9e763f6ae028654a3d35a 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -1761,6 +1761,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info) btrfs_err(info, "bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups", cache->key.objectid); + btrfs_put_block_group(cache); ret = -EINVAL; goto error; } diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 19d669d12ca15226237e698630d7514b65004a88..fe2b8765d9e6b4fc6e991028895580a7c5211426 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -734,8 +734,6 @@ struct btrfs_fs_info { struct btrfs_workqueue *fixup_workers; struct btrfs_workqueue *delayed_workers; - /* the extent workers do delayed refs on the extent allocation tree */ - struct btrfs_workqueue *extent_workers; struct task_struct *transaction_kthread; struct task_struct *cleaner_kthread; u32 thread_pool_size; @@ -2489,8 +2487,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, int nitems, bool use_global_rsv); void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *rsv); -void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes, - bool qgroup_free); +void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes); int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes); u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo); diff --git a/fs/btrfs/delalloc-space.c b/fs/btrfs/delalloc-space.c index d949d7d2abed8489baa5318f5e56a0d1462fb5bd..db9f2c58eb4af481158bb8a635a5f6a7872d4877 100644 --- a/fs/btrfs/delalloc-space.c +++ b/fs/btrfs/delalloc-space.c @@ -381,7 +381,6 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes) out_qgroup: btrfs_qgroup_free_meta_prealloc(root, qgroup_reserve); out_fail: - btrfs_inode_rsv_release(inode, true); if (delalloc_lock) mutex_unlock(&inode->delalloc_mutex); return ret; @@ -418,7 +417,6 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, * btrfs_delalloc_release_extents - release our outstanding_extents * @inode: the inode to balance the reservation for. * @num_bytes: the number of bytes we originally reserved with - * @qgroup_free: do we need to free qgroup meta reservation or convert them. * * When we reserve space we increase outstanding_extents for the extents we may * add. Once we've set the range as delalloc or created our ordered extents we @@ -426,8 +424,7 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, * temporarily tracked outstanding_extents. This _must_ be used in conjunction * with btrfs_delalloc_reserve_metadata. */ -void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes, - bool qgroup_free) +void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes) { struct btrfs_fs_info *fs_info = inode->root->fs_info; unsigned num_extents; @@ -441,7 +438,7 @@ void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes, if (btrfs_is_testing(fs_info)) return; - btrfs_inode_rsv_release(inode, qgroup_free); + btrfs_inode_rsv_release(inode, true); } /** diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 044981cf6df9149cd28d0f3c89cbe05b3be39e12..402b61bf345cd55dddd2efed7cf27576ef262a14 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2008,7 +2008,6 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info) btrfs_destroy_workqueue(fs_info->readahead_workers); btrfs_destroy_workqueue(fs_info->flush_workers); btrfs_destroy_workqueue(fs_info->qgroup_rescan_workers); - btrfs_destroy_workqueue(fs_info->extent_workers); /* * Now that all other work queues are destroyed, we can safely destroy * the queues used for metadata I/O, since tasks from those other work @@ -2214,10 +2213,6 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info, max_active, 2); fs_info->qgroup_rescan_workers = btrfs_alloc_workqueue(fs_info, "qgroup-rescan", flags, 1, 0); - fs_info->extent_workers = - btrfs_alloc_workqueue(fs_info, "extent-refs", flags, - min_t(u64, fs_devices->num_devices, - max_active), 8); if (!(fs_info->workers && fs_info->delalloc_workers && fs_info->submit_workers && fs_info->flush_workers && @@ -2228,7 +2223,6 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info, fs_info->endio_freespace_worker && fs_info->rmw_workers && fs_info->caching_workers && fs_info->readahead_workers && fs_info->fixup_workers && fs_info->delayed_workers && - fs_info->extent_workers && fs_info->qgroup_rescan_workers)) { return -ENOMEM; } diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 27e5b269e729f1de0404fd1811c563a93f47545f..435a502a32261071d3bd4ac4e24d75367a349bbb 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1692,7 +1692,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb, force_page_uptodate); if (ret) { btrfs_delalloc_release_extents(BTRFS_I(inode), - reserve_bytes, true); + reserve_bytes); break; } @@ -1704,7 +1704,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb, if (extents_locked == -EAGAIN) goto again; btrfs_delalloc_release_extents(BTRFS_I(inode), - reserve_bytes, true); + reserve_bytes); ret = extents_locked; break; } @@ -1772,8 +1772,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb, else free_extent_state(cached_state); - btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes, - true); + btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes); if (ret) { btrfs_drop_pages(pages, num_pages); break; @@ -2068,25 +2067,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) struct btrfs_trans_handle *trans; struct btrfs_log_ctx ctx; int ret = 0, err; - u64 len; - /* - * If the inode needs a full sync, make sure we use a full range to - * avoid log tree corruption, due to hole detection racing with ordered - * extent completion for adjacent ranges, and assertion failures during - * hole detection. - */ - if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, - &BTRFS_I(inode)->runtime_flags)) { - start = 0; - end = LLONG_MAX; - } - - /* - * The range length can be represented by u64, we have to do the typecasts - * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync() - */ - len = (u64)end - (u64)start + 1; trace_btrfs_sync_file(file, datasync); btrfs_init_log_ctx(&ctx, inode); @@ -2112,6 +2093,19 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) atomic_inc(&root->log_batch); + /* + * If the inode needs a full sync, make sure we use a full range to + * avoid log tree corruption, due to hole detection racing with ordered + * extent completion for adjacent ranges, and assertion failures during + * hole detection. Do this while holding the inode lock, to avoid races + * with other tasks. + */ + if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, + &BTRFS_I(inode)->runtime_flags)) { + start = 0; + end = LLONG_MAX; + } + /* * Before we acquired the inode's lock, someone may have dirtied more * pages in the target range. We need to make sure that writeback for @@ -2139,8 +2133,11 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) /* * We have to do this here to avoid the priority inversion of waiting on * IO of a lower priority task while holding a transaction open. + * + * Also, the range length can be represented by u64, we have to do the + * typecasts to avoid signed overflow if it's [0, LLONG_MAX]. */ - ret = btrfs_wait_ordered_range(inode, start, len); + ret = btrfs_wait_ordered_range(inode, start, (u64)end - (u64)start + 1); if (ret) { up_write(&BTRFS_I(inode)->dio_sem); inode_unlock(inode); diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 63cad7865d751dd96f2e364fdbd6c92c967a7c6e..37345fb6191d774aff9b8b4fbf57301afab83e98 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -501,13 +501,13 @@ int btrfs_save_ino_cache(struct btrfs_root *root, ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc, prealloc, prealloc, &alloc_hint); if (ret) { - btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, true); + btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc); btrfs_delalloc_release_metadata(BTRFS_I(inode), prealloc, true); goto out_put; } ret = btrfs_write_out_ino_cache(root, trans, path, inode); - btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, false); + btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc); out_put: iput(inode); out_release: diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0f2754eaa05b67ec83858511eeb701d92191e439..c3f386b7cc0bd4d1b38fab14b56d1eec3c576d94 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2206,7 +2206,7 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work) ClearPageChecked(page); set_page_dirty(page); - btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, false); + btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE); out: unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end, &cached_state); @@ -4951,7 +4951,7 @@ int btrfs_truncate_block(struct inode *inode, loff_t from, loff_t len, if (!page) { btrfs_delalloc_release_space(inode, data_reserved, block_start, blocksize, true); - btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, true); + btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize); ret = -ENOMEM; goto out; } @@ -5018,7 +5018,7 @@ int btrfs_truncate_block(struct inode *inode, loff_t from, loff_t len, if (ret) btrfs_delalloc_release_space(inode, data_reserved, block_start, blocksize, true); - btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, (ret != 0)); + btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize); unlock_page(page); put_page(page); out: @@ -8709,7 +8709,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) } else if (ret >= 0 && (size_t)ret < count) btrfs_delalloc_release_space(inode, data_reserved, offset, count - (size_t)ret, true); - btrfs_delalloc_release_extents(BTRFS_I(inode), count, false); + btrfs_delalloc_release_extents(BTRFS_I(inode), count); } out: if (wakeup) @@ -9059,7 +9059,7 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf) unlock_extent_cached(io_tree, page_start, page_end, &cached_state); if (!ret2) { - btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, true); + btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE); sb_end_pagefault(inode->i_sb); extent_changeset_free(data_reserved); return VM_FAULT_LOCKED; @@ -9068,7 +9068,7 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf) out_unlock: unlock_page(page); out: - btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, (ret != 0)); + btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE); btrfs_delalloc_release_space(inode, data_reserved, page_start, reserved_space, (ret != 0)); out_noreserve: diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index de730e56d3f5106ee97d7fa316ee5e855487d954..7c145a41decd9aa135992031cdcf4c110e876a8e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1360,8 +1360,7 @@ static int cluster_pages_for_defrag(struct inode *inode, unlock_page(pages[i]); put_page(pages[i]); } - btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT, - false); + btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT); extent_changeset_free(data_reserved); return i_done; out: @@ -1372,8 +1371,7 @@ static int cluster_pages_for_defrag(struct inode *inode, btrfs_delalloc_release_space(inode, data_reserved, start_index << PAGE_SHIFT, page_cnt << PAGE_SHIFT, true); - btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT, - true); + btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT); extent_changeset_free(data_reserved); return ret; diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index c4bb69941c77c721a7b6c69bb11d83938bfb69d2..3ad151655eb88680b75cfbda5c8005daf3d5d05a 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -3629,7 +3629,7 @@ int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, return 0; BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize)); - trace_qgroup_meta_reserve(root, type, (s64)num_bytes); + trace_qgroup_meta_reserve(root, (s64)num_bytes, type); ret = qgroup_reserve(root, num_bytes, enforce, type); if (ret < 0) return ret; @@ -3676,7 +3676,7 @@ void __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes, */ num_bytes = sub_root_meta_rsv(root, num_bytes, type); BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize)); - trace_qgroup_meta_reserve(root, type, -(s64)num_bytes); + trace_qgroup_meta_reserve(root, -(s64)num_bytes, type); btrfs_qgroup_free_refroot(fs_info, root->root_key.objectid, num_bytes, type); } diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 00504657b60225f5c00346f16098609db679f90e..5cd42b66818cd4ab3b935b809de32aca91a3fefc 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -3277,6 +3277,8 @@ static int relocate_file_extent_cluster(struct inode *inode, if (!page) { btrfs_delalloc_release_metadata(BTRFS_I(inode), PAGE_SIZE, true); + btrfs_delalloc_release_extents(BTRFS_I(inode), + PAGE_SIZE); ret = -ENOMEM; goto out; } @@ -3297,7 +3299,7 @@ static int relocate_file_extent_cluster(struct inode *inode, btrfs_delalloc_release_metadata(BTRFS_I(inode), PAGE_SIZE, true); btrfs_delalloc_release_extents(BTRFS_I(inode), - PAGE_SIZE, true); + PAGE_SIZE); ret = -EIO; goto out; } @@ -3326,7 +3328,7 @@ static int relocate_file_extent_cluster(struct inode *inode, btrfs_delalloc_release_metadata(BTRFS_I(inode), PAGE_SIZE, true); btrfs_delalloc_release_extents(BTRFS_I(inode), - PAGE_SIZE, true); + PAGE_SIZE); clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end, @@ -3342,8 +3344,7 @@ static int relocate_file_extent_cluster(struct inode *inode, put_page(page); index++; - btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, - false); + btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE); balance_dirty_pages_ratelimited(inode->i_mapping); btrfs_throttle(fs_info); } diff --git a/fs/buffer.c b/fs/buffer.c index 86a38b979323547cb01c3c0f0257ec5dd93efc6d..5d1f420de95b0328182f23fbea8c83b19a4fdc5d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -47,6 +47,7 @@ #include #include #include +#include static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, @@ -3068,6 +3069,8 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, */ bio = bio_alloc(GFP_NOIO, 1); + fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO | __GFP_NOFAIL); + bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio_set_dev(bio, bh->b_bdev); bio->bi_write_hint = write_hint; diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index a8a8f84f3bbfae462ba8001faa0dac7721ce883f..a5163296d9d9b10518a1942ee95c2a96f2301cf6 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -384,8 +384,8 @@ static int parse_reply_info_readdir(void **p, void *end, } done: - if (*p != end) - goto bad; + /* Skip over any unrecognized fields */ + *p = end; return 0; bad: @@ -406,12 +406,10 @@ static int parse_reply_info_filelock(void **p, void *end, goto bad; info->filelock_reply = *p; - *p += sizeof(*info->filelock_reply); - if (unlikely(*p != end)) - goto bad; + /* Skip over any unrecognized fields */ + *p = end; return 0; - bad: return -EIO; } @@ -425,18 +423,21 @@ static int parse_reply_info_create(void **p, void *end, { if (features == (u64)-1 || (features & CEPH_FEATURE_REPLY_CREATE_INODE)) { + /* Malformed reply? */ if (*p == end) { info->has_create_ino = false; } else { info->has_create_ino = true; - info->ino = ceph_decode_64(p); + ceph_decode_64_safe(p, end, info->ino, bad); } + } else { + if (*p != end) + goto bad; } - if (unlikely(*p != end)) - goto bad; + /* Skip over any unrecognized fields */ + *p = end; return 0; - bad: return -EIO; } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c049c7b3aa87a51d48e4d5afe6231c87bee1a910..1a135d1b85bd8c3dca017660d1c786a4d4578280 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -169,7 +169,13 @@ cifs_read_super(struct super_block *sb) else sb->s_maxbytes = MAX_NON_LFS; - /* Some very old servers like DOS and OS/2 used 2 second granularity */ + /* + * Some very old servers like DOS and OS/2 used 2 second granularity + * (while all current servers use 100ns granularity - see MS-DTYP) + * but 1 second is the maximum allowed granularity for the VFS + * so for old servers set time granularity to 1 second while for + * everything else (current servers) set it to 100ns. + */ if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) && ((tcon->ses->capabilities & tcon->ses->server->vals->cap_nt_find) == 0) && diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 50dfd9049370dfc56bdd503f3b2b6c84e354e510..d78bfcc191560804b694b965a381b21f7b5962f2 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1391,6 +1391,11 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); struct cifsInodeInfo { bool can_cache_brlcks; struct list_head llist; /* locks helb by this inode */ + /* + * NOTE: Some code paths call down_read(lock_sem) twice, so + * we must always use use cifs_down_write() instead of down_write() + * for this semaphore to avoid deadlocks. + */ struct rw_semaphore lock_sem; /* protect the fields above */ /* BB add in lists for dirty pages i.e. write caching info for oplock */ struct list_head openFileList; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index e53e9f62b87b7b043f11010877ab59c5937c7014..fe597d3d52088366615c5ec5d295ee7218f4d9ed 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -170,6 +170,7 @@ extern int cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, const unsigned int xid); extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile); +extern void cifs_down_write(struct rw_semaphore *sem); extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, struct tcon_link *tlink, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a64dfa95a925acaefa19ddc027ff2c454ada96a8..ccaa8bad336f9d7e2b67cb1364a4ca4b6f1718d4 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -564,9 +564,11 @@ cifs_reconnect(struct TCP_Server_Info *server) spin_lock(&GlobalMid_Lock); list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); + kref_get(&mid_entry->refcount); if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) mid_entry->mid_state = MID_RETRY_NEEDED; list_move(&mid_entry->qhead, &retry_list); + mid_entry->mid_flags |= MID_DELETED; } spin_unlock(&GlobalMid_Lock); mutex_unlock(&server->srv_mutex); @@ -576,6 +578,7 @@ cifs_reconnect(struct TCP_Server_Info *server) mid_entry = list_entry(tmp, struct mid_q_entry, qhead); list_del_init(&mid_entry->qhead); mid_entry->callback(mid_entry); + cifs_mid_q_entry_release(mid_entry); } if (cifs_rdma_enabled(server)) { @@ -895,8 +898,10 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) if (mid->mid_flags & MID_DELETED) printk_once(KERN_WARNING "trying to dequeue a deleted mid\n"); - else + else { list_del_init(&mid->qhead); + mid->mid_flags |= MID_DELETED; + } spin_unlock(&GlobalMid_Lock); } @@ -966,8 +971,10 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid); + kref_get(&mid_entry->refcount); mid_entry->mid_state = MID_SHUTDOWN; list_move(&mid_entry->qhead, &dispose_list); + mid_entry->mid_flags |= MID_DELETED; } spin_unlock(&GlobalMid_Lock); @@ -977,6 +984,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid); list_del_init(&mid_entry->qhead); mid_entry->callback(mid_entry); + cifs_mid_q_entry_release(mid_entry); } /* 1/8th of sec is more than enough time for them to exit */ msleep(125); @@ -3882,8 +3890,12 @@ generic_ip_connect(struct TCP_Server_Info *server) rc = socket->ops->connect(socket, saddr, slen, server->noblockcnt ? O_NONBLOCK : 0); - - if (rc == -EINPROGRESS) + /* + * When mounting SMB root file systems, we do not want to block in + * connect. Otherwise bail out and then let cifs_reconnect() perform + * reconnect failover - if possible. + */ + if (server->noblockcnt && rc == -EINPROGRESS) rc = 0; if (rc < 0) { cifs_dbg(FYI, "Error %d connecting to server\n", rc); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5ad15de2bb4f950cf88d72f3d15b3b3132e72bcd..fa7b0fa72bb360d7133b13b05788e1e591faf547 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -281,6 +281,13 @@ cifs_has_mand_locks(struct cifsInodeInfo *cinode) return has_locks; } +void +cifs_down_write(struct rw_semaphore *sem) +{ + while (!down_write_trylock(sem)) + msleep(10); +} + struct cifsFileInfo * cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, struct tcon_link *tlink, __u32 oplock) @@ -306,7 +313,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, INIT_LIST_HEAD(&fdlocks->locks); fdlocks->cfile = cfile; cfile->llist = fdlocks; - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); list_add(&fdlocks->llist, &cinode->llist); up_write(&cinode->lock_sem); @@ -405,10 +412,11 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler) bool oplock_break_cancelled; spin_lock(&tcon->open_file_lock); - + spin_lock(&cifsi->open_file_lock); spin_lock(&cifs_file->file_info_lock); if (--cifs_file->count > 0) { spin_unlock(&cifs_file->file_info_lock); + spin_unlock(&cifsi->open_file_lock); spin_unlock(&tcon->open_file_lock); return; } @@ -421,9 +429,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler) cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open); /* remove it from the lists */ - spin_lock(&cifsi->open_file_lock); list_del(&cifs_file->flist); - spin_unlock(&cifsi->open_file_lock); list_del(&cifs_file->tlist); atomic_dec(&tcon->num_local_opens); @@ -440,6 +446,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler) cifs_set_oplock_level(cifsi, 0); } + spin_unlock(&cifsi->open_file_lock); spin_unlock(&tcon->open_file_lock); oplock_break_cancelled = wait_oplock_handler ? @@ -464,7 +471,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler) * Delete any outstanding lock records. We'll lose them when the file * is closed anyway. */ - down_write(&cifsi->lock_sem); + cifs_down_write(&cifsi->lock_sem); list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) { list_del(&li->llist); cifs_del_lock_waiters(li); @@ -1027,7 +1034,7 @@ static void cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) { struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); list_add_tail(&lock->llist, &cfile->llist->locks); up_write(&cinode->lock_sem); } @@ -1049,7 +1056,7 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, try_again: exist = false; - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, lock->type, lock->flags, &conf_lock, @@ -1072,7 +1079,7 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, (lock->blist.next == &lock->blist)); if (!rc) goto try_again; - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); list_del_init(&lock->blist); } @@ -1125,7 +1132,7 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock) return rc; try_again: - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); if (!cinode->can_cache_brlcks) { up_write(&cinode->lock_sem); return rc; @@ -1331,7 +1338,7 @@ cifs_push_locks(struct cifsFileInfo *cfile) int rc = 0; /* we are going to update can_cache_brlcks here - need a write access */ - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); if (!cinode->can_cache_brlcks) { up_write(&cinode->lock_sem); return rc; @@ -1522,7 +1529,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, if (!buf) return -ENOMEM; - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); for (i = 0; i < 2; i++) { cur = buf; num = 0; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 5dcc95b38310b63fabbf5b0404cbfb9776615798..df9377828e2f435bdb32339f48c2ad08ac9bdd32 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -2475,9 +2475,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid); cifsFileInfo_put(wfile); if (rc) - return rc; + goto cifs_setattr_exit; } else if (rc != -EBADF) - return rc; + goto cifs_setattr_exit; else rc = 0; } diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index b7421a0963195137474d9e3a15075796743c6157..514810694c0f5a7b48bfa6139401beb8c40c68cf 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -171,6 +171,9 @@ cifs_get_next_mid(struct TCP_Server_Info *server) /* we do not want to loop forever */ last_mid = cur_mid; cur_mid++; + /* avoid 0xFFFF MID */ + if (cur_mid == 0xffff) + cur_mid++; /* * This nested loop looks more expensive than it is. diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index e6a1fc72018fd1821f8499a70eebe6edd7400bdc..8b0b512c57920cebd5a022c2357a31e376cf87ed 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -145,7 +145,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, cur = buf; - down_write(&cinode->lock_sem); + cifs_down_write(&cinode->lock_sem); list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { if (flock->fl_start > li->offset || (flock->fl_start + length) < diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 4c092259646740da18a7e3be2b31d1647320aaa4..cd55af9b7cc5aca5669fb53018efb0ea29494bff 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -4084,6 +4084,7 @@ static void smb2_decrypt_offload(struct work_struct *work) kfree(dw->ppages); cifs_small_buf_release(dw->buf); + kfree(dw); } @@ -4157,7 +4158,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, dw->server = server; dw->ppages = pages; dw->len = len; - queue_work(cifsiod_wq, &dw->decrypt); + queue_work(decrypt_wq, &dw->decrypt); *num_mids = 0; /* worker thread takes care of finding mid */ return -1; } diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 308ad0f495e10d513f9219e92d8ade62558337f6..ca3de62688d6e8fab18504ef09cc4be5ac9c709a 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -86,22 +86,8 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) static void _cifs_mid_q_entry_release(struct kref *refcount) { - struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry, - refcount); - - mempool_free(mid, cifs_mid_poolp); -} - -void cifs_mid_q_entry_release(struct mid_q_entry *midEntry) -{ - spin_lock(&GlobalMid_Lock); - kref_put(&midEntry->refcount, _cifs_mid_q_entry_release); - spin_unlock(&GlobalMid_Lock); -} - -void -DeleteMidQEntry(struct mid_q_entry *midEntry) -{ + struct mid_q_entry *midEntry = + container_of(refcount, struct mid_q_entry, refcount); #ifdef CONFIG_CIFS_STATS2 __le16 command = midEntry->server->vals->lock_cmd; __u16 smb_cmd = le16_to_cpu(midEntry->command); @@ -166,6 +152,19 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) } } #endif + + mempool_free(midEntry, cifs_mid_poolp); +} + +void cifs_mid_q_entry_release(struct mid_q_entry *midEntry) +{ + spin_lock(&GlobalMid_Lock); + kref_put(&midEntry->refcount, _cifs_mid_q_entry_release); + spin_unlock(&GlobalMid_Lock); +} + +void DeleteMidQEntry(struct mid_q_entry *midEntry) +{ cifs_mid_q_entry_release(midEntry); } @@ -173,8 +172,10 @@ void cifs_delete_mid(struct mid_q_entry *mid) { spin_lock(&GlobalMid_Lock); - list_del_init(&mid->qhead); - mid->mid_flags |= MID_DELETED; + if (!(mid->mid_flags & MID_DELETED)) { + list_del_init(&mid->qhead); + mid->mid_flags |= MID_DELETED; + } spin_unlock(&GlobalMid_Lock); DeleteMidQEntry(mid); @@ -872,7 +873,10 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) rc = -EHOSTDOWN; break; default: - list_del_init(&mid->qhead); + if (!(mid->mid_flags & MID_DELETED)) { + list_del_init(&mid->qhead); + mid->mid_flags |= MID_DELETED; + } cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n", __func__, mid->mid, mid->mid_state); rc = -EIO; diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index ff5a1746cbae4cc2f9fa26c30b6e85fb7f56da28..5061aa5462029859671f16376fdb360542861fc7 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -16,3 +16,9 @@ config FS_ENCRYPTION efficient since it avoids caching the encrypted and decrypted pages in the page cache. Currently Ext4, F2FS and UBIFS make use of this feature. + +config FS_ENCRYPTION_INLINE_CRYPT + bool "Enable fscrypt to use inline crypto" + depends on FS_ENCRYPTION && BLK_INLINE_ENCRYPTION + help + Enable fscrypt to use inline encryption hardware if available. diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 232e2bb5a337b2c0dd6df0332f16deb069733c1b..652c7180ec6de942611ff550652548f05c6af666 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -11,3 +11,4 @@ fscrypto-y := crypto.o \ policy.o fscrypto-$(CONFIG_BLOCK) += bio.o +fscrypto-$(CONFIG_FS_ENCRYPTION_INLINE_CRYPT) += inline_crypt.o diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index 82da2510721f6b7189af9026a2854c8dbe089c40..956798debf71105a1fa5097f0c16ec2c34c8e361 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c @@ -26,7 +26,7 @@ #include #include "fscrypt_private.h" -static void __fscrypt_decrypt_bio(struct bio *bio, bool done) +void fscrypt_decrypt_bio(struct bio *bio) { struct bio_vec *bv; struct bvec_iter_all iter_all; @@ -37,62 +37,47 @@ static void __fscrypt_decrypt_bio(struct bio *bio, bool done) bv->bv_offset); if (ret) SetPageError(page); - else if (done) - SetPageUptodate(page); - if (done) - unlock_page(page); } } - -void fscrypt_decrypt_bio(struct bio *bio) -{ - __fscrypt_decrypt_bio(bio, false); -} EXPORT_SYMBOL(fscrypt_decrypt_bio); -static void completion_pages(struct work_struct *work) -{ - struct fscrypt_ctx *ctx = container_of(work, struct fscrypt_ctx, work); - struct bio *bio = ctx->bio; - - __fscrypt_decrypt_bio(bio, true); - fscrypt_release_ctx(ctx); - bio_put(bio); -} - -void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio) -{ - INIT_WORK(&ctx->work, completion_pages); - ctx->bio = bio; - fscrypt_enqueue_decrypt_work(&ctx->work); -} -EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio); - int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, sector_t pblk, unsigned int len) { const unsigned int blockbits = inode->i_blkbits; const unsigned int blocksize = 1 << blockbits; + const bool inlinecrypt = fscrypt_inode_uses_inline_crypto(inode); struct page *ciphertext_page; struct bio *bio; int ret, err = 0; - ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT); - if (!ciphertext_page) - return -ENOMEM; + if (inlinecrypt) { + ciphertext_page = ZERO_PAGE(0); + } else { + ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT); + if (!ciphertext_page) + return -ENOMEM; + } while (len--) { - err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, - ZERO_PAGE(0), ciphertext_page, - blocksize, 0, GFP_NOFS); - if (err) - goto errout; + if (!inlinecrypt) { + err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, + ZERO_PAGE(0), ciphertext_page, + blocksize, 0, GFP_NOFS); + if (err) + goto errout; + } bio = bio_alloc(GFP_NOWAIT, 1); if (!bio) { err = -ENOMEM; goto errout; } + err = fscrypt_set_bio_crypt_ctx(bio, inode, lblk, GFP_NOIO); + if (err) { + bio_put(bio); + goto errout; + } bio_set_dev(bio, inode->i_sb->s_bdev); bio->bi_iter.bi_sector = pblk << (blockbits - 9); bio_set_op_attrs(bio, REQ_OP_WRITE, 0); @@ -114,7 +99,8 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, } err = 0; errout: - fscrypt_free_bounce_page(ciphertext_page); + if (!inlinecrypt) + fscrypt_free_bounce_page(ciphertext_page); return err; } EXPORT_SYMBOL(fscrypt_zeroout_range); diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 32a7ad0098cc28b7739d225e52d4898d812f939b..3719efa546c6579b38dbd6fcf2a8b49b5ceb32d5 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -27,29 +27,20 @@ #include #include #include -#include #include #include "fscrypt_private.h" static unsigned int num_prealloc_crypto_pages = 32; -static unsigned int num_prealloc_crypto_ctxs = 128; module_param(num_prealloc_crypto_pages, uint, 0444); MODULE_PARM_DESC(num_prealloc_crypto_pages, "Number of crypto pages to preallocate"); -module_param(num_prealloc_crypto_ctxs, uint, 0444); -MODULE_PARM_DESC(num_prealloc_crypto_ctxs, - "Number of crypto contexts to preallocate"); static mempool_t *fscrypt_bounce_page_pool = NULL; -static LIST_HEAD(fscrypt_free_ctxs); -static DEFINE_SPINLOCK(fscrypt_ctx_lock); - static struct workqueue_struct *fscrypt_read_workqueue; static DEFINE_MUTEX(fscrypt_init_mutex); -static struct kmem_cache *fscrypt_ctx_cachep; struct kmem_cache *fscrypt_info_cachep; void fscrypt_enqueue_decrypt_work(struct work_struct *work) @@ -58,62 +49,6 @@ void fscrypt_enqueue_decrypt_work(struct work_struct *work) } EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work); -/** - * fscrypt_release_ctx() - Release a decryption context - * @ctx: The decryption context to release. - * - * If the decryption context was allocated from the pre-allocated pool, return - * it to that pool. Else, free it. - */ -void fscrypt_release_ctx(struct fscrypt_ctx *ctx) -{ - unsigned long flags; - - if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) { - kmem_cache_free(fscrypt_ctx_cachep, ctx); - } else { - spin_lock_irqsave(&fscrypt_ctx_lock, flags); - list_add(&ctx->free_list, &fscrypt_free_ctxs); - spin_unlock_irqrestore(&fscrypt_ctx_lock, flags); - } -} -EXPORT_SYMBOL(fscrypt_release_ctx); - -/** - * fscrypt_get_ctx() - Get a decryption context - * @gfp_flags: The gfp flag for memory allocation - * - * Allocate and initialize a decryption context. - * - * Return: A new decryption context on success; an ERR_PTR() otherwise. - */ -struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags) -{ - struct fscrypt_ctx *ctx; - unsigned long flags; - - /* - * First try getting a ctx from the free list so that we don't have to - * call into the slab allocator. - */ - spin_lock_irqsave(&fscrypt_ctx_lock, flags); - ctx = list_first_entry_or_null(&fscrypt_free_ctxs, - struct fscrypt_ctx, free_list); - if (ctx) - list_del(&ctx->free_list); - spin_unlock_irqrestore(&fscrypt_ctx_lock, flags); - if (!ctx) { - ctx = kmem_cache_zalloc(fscrypt_ctx_cachep, gfp_flags); - if (!ctx) - return ERR_PTR(-ENOMEM); - ctx->flags |= FS_CTX_REQUIRES_FREE_ENCRYPT_FL; - } else { - ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL; - } - return ctx; -} -EXPORT_SYMBOL(fscrypt_get_ctx); - struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags) { return mempool_alloc(fscrypt_bounce_page_pool, gfp_flags); @@ -138,14 +73,17 @@ EXPORT_SYMBOL(fscrypt_free_bounce_page); void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, const struct fscrypt_info *ci) { + u8 flags = fscrypt_policy_flags(&ci->ci_policy); + memset(iv, 0, ci->ci_mode->ivsize); - iv->lblk_num = cpu_to_le64(lblk_num); - if (fscrypt_is_direct_key_policy(&ci->ci_policy)) + if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { + WARN_ON_ONCE((u32)lblk_num != lblk_num); + lblk_num |= (u64)ci->ci_inode->i_ino << 32; + } else if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE); - - if (ci->ci_essiv_tfm != NULL) - crypto_cipher_encrypt_one(ci->ci_essiv_tfm, iv->raw, iv->raw); + } + iv->lblk_num = cpu_to_le64(lblk_num); } /* Encrypt or decrypt a single filesystem block of file contents */ @@ -396,17 +334,6 @@ const struct dentry_operations fscrypt_d_ops = { .d_revalidate = fscrypt_d_revalidate, }; -static void fscrypt_destroy(void) -{ - struct fscrypt_ctx *pos, *n; - - list_for_each_entry_safe(pos, n, &fscrypt_free_ctxs, free_list) - kmem_cache_free(fscrypt_ctx_cachep, pos); - INIT_LIST_HEAD(&fscrypt_free_ctxs); - mempool_destroy(fscrypt_bounce_page_pool); - fscrypt_bounce_page_pool = NULL; -} - /** * fscrypt_initialize() - allocate major buffers for fs encryption. * @cop_flags: fscrypt operations flags @@ -414,11 +341,11 @@ static void fscrypt_destroy(void) * We only call this when we start accessing encrypted files, since it * results in memory getting allocated that wouldn't otherwise be used. * - * Return: Zero on success, non-zero otherwise. + * Return: 0 on success; -errno on failure */ int fscrypt_initialize(unsigned int cop_flags) { - int i, res = -ENOMEM; + int err = 0; /* No need to allocate a bounce page pool if this FS won't use it. */ if (cop_flags & FS_CFLG_OWN_PAGES) @@ -426,29 +353,18 @@ int fscrypt_initialize(unsigned int cop_flags) mutex_lock(&fscrypt_init_mutex); if (fscrypt_bounce_page_pool) - goto already_initialized; - - for (i = 0; i < num_prealloc_crypto_ctxs; i++) { - struct fscrypt_ctx *ctx; - - ctx = kmem_cache_zalloc(fscrypt_ctx_cachep, GFP_NOFS); - if (!ctx) - goto fail; - list_add(&ctx->free_list, &fscrypt_free_ctxs); - } + goto out_unlock; + err = -ENOMEM; fscrypt_bounce_page_pool = mempool_create_page_pool(num_prealloc_crypto_pages, 0); if (!fscrypt_bounce_page_pool) - goto fail; + goto out_unlock; -already_initialized: - mutex_unlock(&fscrypt_init_mutex); - return 0; -fail: - fscrypt_destroy(); + err = 0; +out_unlock: mutex_unlock(&fscrypt_init_mutex); - return res; + return err; } void fscrypt_msg(const struct inode *inode, const char *level, @@ -494,13 +410,9 @@ static int __init fscrypt_init(void) if (!fscrypt_read_workqueue) goto fail; - fscrypt_ctx_cachep = KMEM_CACHE(fscrypt_ctx, SLAB_RECLAIM_ACCOUNT); - if (!fscrypt_ctx_cachep) - goto fail_free_queue; - fscrypt_info_cachep = KMEM_CACHE(fscrypt_info, SLAB_RECLAIM_ACCOUNT); if (!fscrypt_info_cachep) - goto fail_free_ctx; + goto fail_free_queue; err = fscrypt_init_keyring(); if (err) @@ -510,8 +422,6 @@ static int __init fscrypt_init(void) fail_free_info: kmem_cache_destroy(fscrypt_info_cachep); -fail_free_ctx: - kmem_cache_destroy(fscrypt_ctx_cachep); fail_free_queue: destroy_workqueue(fscrypt_read_workqueue); fail: diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index e84efc01512e4e5dbfc2eab7efaf83101022110c..c731bd4245c541ad57e7c2fe007986a9495c8080 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -13,6 +13,9 @@ #include #include +#include + +struct fscrypt_master_key; #define CONST_STRLEN(str) (sizeof(str) - 1) @@ -163,11 +166,16 @@ struct fscrypt_info { /* The actual crypto transform used for encryption and decryption */ struct crypto_skcipher *ci_ctfm; +#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT /* - * Cipher for ESSIV IV generation. Only set for CBC contents - * encryption, otherwise is NULL. + * The raw key for inline encryption, if this file is using inline + * encryption rather than the traditional filesystem layer encryption. */ - struct crypto_cipher *ci_essiv_tfm; + const u8 *ci_inline_crypt_key; +#endif + + /* True if the key should be freed when this fscrypt_info is freed */ + bool ci_owns_key; /* * Encryption mode used for this inode. It corresponds to either the @@ -209,8 +217,6 @@ typedef enum { FS_ENCRYPT, } fscrypt_direction_t; -#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 - static inline bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) { @@ -289,7 +295,8 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, */ #define HKDF_CONTEXT_KEY_IDENTIFIER 1 #define HKDF_CONTEXT_PER_FILE_KEY 2 -#define HKDF_CONTEXT_PER_MODE_KEY 3 +#define HKDF_CONTEXT_DIRECT_KEY 3 +#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, const u8 *info, unsigned int infolen, @@ -297,6 +304,54 @@ extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf); +/* inline_crypt.c */ +#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT +extern bool fscrypt_should_use_inline_encryption(const struct fscrypt_info *ci); + +extern int fscrypt_set_inline_crypt_key(struct fscrypt_info *ci, + const u8 *derived_key); + +extern void fscrypt_free_inline_crypt_key(struct fscrypt_info *ci); + +extern int fscrypt_setup_per_mode_inline_crypt_key( + struct fscrypt_info *ci, + struct fscrypt_master_key *mk); + +extern void fscrypt_evict_inline_crypt_keys(struct fscrypt_master_key *mk); + +#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ + +static inline bool fscrypt_should_use_inline_encryption( + const struct fscrypt_info *ci) +{ + return false; +} + +static inline int fscrypt_set_inline_crypt_key(struct fscrypt_info *ci, + const u8 *derived_key) +{ + WARN_ON(1); + return -EOPNOTSUPP; +} + +static inline void fscrypt_free_inline_crypt_key(struct fscrypt_info *ci) +{ +} + +static inline int fscrypt_setup_per_mode_inline_crypt_key( + struct fscrypt_info *ci, + struct fscrypt_master_key *mk) +{ + WARN_ON(1); + return -EOPNOTSUPP; +} + +static inline void fscrypt_evict_inline_crypt_keys( + struct fscrypt_master_key *mk) +{ +} +#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ + /* keyring.c */ /* @@ -386,9 +441,25 @@ struct fscrypt_master_key { struct list_head mk_decrypted_inodes; spinlock_t mk_decrypted_inodes_lock; - /* Per-mode tfms for DIRECT_KEY policies, allocated on-demand */ - struct crypto_skcipher *mk_mode_keys[__FSCRYPT_MODE_MAX + 1]; + /* Crypto API transforms for DIRECT_KEY policies, allocated on-demand */ + struct crypto_skcipher *mk_direct_tfms[__FSCRYPT_MODE_MAX + 1]; + + /* + * Crypto API transforms for filesystem-layer implementation of + * IV_INO_LBLK_64 policies, allocated on-demand. + */ + struct crypto_skcipher *mk_iv_ino_lblk_64_tfms[__FSCRYPT_MODE_MAX + 1]; +#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT + /* Raw keys for IV_INO_LBLK_64 policies, allocated on-demand */ + u8 *mk_iv_ino_lblk_64_raw_keys[__FSCRYPT_MODE_MAX + 1]; + + /* The data unit size being used for inline encryption */ + unsigned int mk_data_unit_size; + + /* The filesystem's block device */ + struct block_device *mk_bdev; +#endif } __randomize_layout; static inline bool @@ -443,10 +514,12 @@ struct fscrypt_mode { const char *cipher_str; int keysize; int ivsize; + enum blk_crypto_mode_num blk_crypto_mode; bool logged_impl_name; - bool needs_essiv; }; +extern struct fscrypt_mode fscrypt_modes[]; + static inline bool fscrypt_mode_supports_direct_key(const struct fscrypt_mode *mode) { diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c new file mode 100644 index 0000000000000000000000000000000000000000..e41c6d66ff0d19b0ac4ba19c356313bb56b1b286 --- /dev/null +++ b/fs/crypto/inline_crypt.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Inline encryption support for fscrypt + * + * Copyright 2019 Google LLC + */ + +/* + * With "inline encryption", the block layer handles the decryption/encryption + * as part of the bio, instead of the filesystem doing the crypto itself via + * crypto API. See Documentation/block/inline-encryption.rst. fscrypt still + * provides the key and IV to use. + */ + +#include +#include +#include +#include + +#include "fscrypt_private.h" + +/* Return true iff inline encryption should be used for this file */ +bool fscrypt_should_use_inline_encryption(const struct fscrypt_info *ci) +{ + const struct inode *inode = ci->ci_inode; + struct super_block *sb = inode->i_sb; + + /* The file must need contents encryption, not filenames encryption */ + if (!S_ISREG(inode->i_mode)) + return false; + + /* blk-crypto must implement the needed encryption algorithm */ + if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID) + return false; + + /* DIRECT_KEY needs a 24+ byte IV, so it can't work with 8-byte DUNs */ + if (fscrypt_is_direct_key_policy(&ci->ci_policy)) + return false; + + /* The filesystem must be mounted with -o inlinecrypt */ + if (!sb->s_cop->inline_crypt_enabled || + !sb->s_cop->inline_crypt_enabled(sb)) + return false; + + return true; +} + +/* Set a per-file inline encryption key (for passing to blk-crypto) */ +int fscrypt_set_inline_crypt_key(struct fscrypt_info *ci, const u8 *derived_key) +{ + const struct fscrypt_mode *mode = ci->ci_mode; + const struct super_block *sb = ci->ci_inode->i_sb; + + ci->ci_inline_crypt_key = kmemdup(derived_key, mode->keysize, GFP_NOFS); + if (!ci->ci_inline_crypt_key) + return -ENOMEM; + ci->ci_owns_key = true; + + return blk_crypto_start_using_mode(mode->blk_crypto_mode, + sb->s_blocksize, + sb->s_bdev->bd_queue); +} + +/* Free a per-file inline encryption key and evict it from blk-crypto */ +void fscrypt_free_inline_crypt_key(struct fscrypt_info *ci) +{ + if (ci->ci_inline_crypt_key != NULL) { + const struct fscrypt_mode *mode = ci->ci_mode; + const struct super_block *sb = ci->ci_inode->i_sb; + + blk_crypto_evict_key(sb->s_bdev->bd_queue, + ci->ci_inline_crypt_key, + mode->blk_crypto_mode, sb->s_blocksize); + kzfree(ci->ci_inline_crypt_key); + } +} + +/* + * Set up ->inline_crypt_key (for passing to blk-crypto) for inodes which use an + * IV_INO_LBLK_64 encryption policy. + * + * Return: 0 on success, -errno on failure + */ +int fscrypt_setup_per_mode_inline_crypt_key(struct fscrypt_info *ci, + struct fscrypt_master_key *mk) +{ + static DEFINE_MUTEX(inline_crypt_setup_mutex); + const struct super_block *sb = ci->ci_inode->i_sb; + struct block_device *bdev = sb->s_bdev; + const struct fscrypt_mode *mode = ci->ci_mode; + const u8 mode_num = mode - fscrypt_modes; + u8 *raw_key; + u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)]; + int err; + + if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX)) + return -EINVAL; + + /* pairs with smp_store_release() below */ + raw_key = smp_load_acquire(&mk->mk_iv_ino_lblk_64_raw_keys[mode_num]); + if (raw_key) { + err = 0; + goto out; + } + + mutex_lock(&inline_crypt_setup_mutex); + + raw_key = mk->mk_iv_ino_lblk_64_raw_keys[mode_num]; + if (raw_key) { + err = 0; + goto out_unlock; + } + + raw_key = kmalloc(mode->keysize, GFP_NOFS); + if (!raw_key) { + err = -ENOMEM; + goto out_unlock; + } + + BUILD_BUG_ON(sizeof(mode_num) != 1); + BUILD_BUG_ON(sizeof(sb->s_uuid) != 16); + BUILD_BUG_ON(sizeof(hkdf_info) != 17); + hkdf_info[0] = mode_num; + memcpy(&hkdf_info[1], &sb->s_uuid, sizeof(sb->s_uuid)); + + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + HKDF_CONTEXT_IV_INO_LBLK_64_KEY, + hkdf_info, sizeof(hkdf_info), + raw_key, mode->keysize); + if (err) + goto out_unlock; + + err = blk_crypto_start_using_mode(mode->blk_crypto_mode, + sb->s_blocksize, bdev->bd_queue); + if (err) + goto out_unlock; + + /* + * When a master key's first inline encryption key is set up, save a + * reference to the filesystem's block device so that the inline + * encryption keys can be evicted when the master key is destroyed. + */ + if (!mk->mk_bdev) { + mk->mk_bdev = bdgrab(bdev); + mk->mk_data_unit_size = sb->s_blocksize; + } + + /* pairs with smp_load_acquire() above */ + smp_store_release(&mk->mk_iv_ino_lblk_64_raw_keys[mode_num], raw_key); + err = 0; +out_unlock: + mutex_unlock(&inline_crypt_setup_mutex); +out: + if (err == 0) { + ci->ci_inline_crypt_key = raw_key; + /* + * Since each struct fscrypt_master_key belongs to a particular + * filesystem (a struct super_block), there should be only one + * block device, and only one data unit size as it should equal + * the filesystem's blocksize (i.e. s_blocksize). + */ + if (WARN_ON(mk->mk_bdev != bdev)) + err = -EINVAL; + if (WARN_ON(mk->mk_data_unit_size != sb->s_blocksize)) + err = -EINVAL; + } else { + kzfree(raw_key); + } + return err; +} + +/* + * Evict per-mode inline encryption keys from blk-crypto when a master key is + * destroyed. + */ +void fscrypt_evict_inline_crypt_keys(struct fscrypt_master_key *mk) +{ + struct block_device *bdev = mk->mk_bdev; + size_t i; + + if (!bdev) /* No inline encryption keys? */ + return; + + for (i = 0; i < ARRAY_SIZE(mk->mk_iv_ino_lblk_64_raw_keys); i++) { + u8 *raw_key = mk->mk_iv_ino_lblk_64_raw_keys[i]; + + if (raw_key != NULL) { + blk_crypto_evict_key(bdev->bd_queue, raw_key, + fscrypt_modes[i].blk_crypto_mode, + mk->mk_data_unit_size); + kzfree(raw_key); + } + } + bdput(bdev); +} + +/** + * fscrypt_inode_uses_inline_crypto - test whether an inode uses inline encryption + * @inode: an inode + * + * Return: true if the inode requires file contents encryption and if the + * encryption should be done in the block layer via blk-crypto rather + * than in the filesystem layer. + */ +bool fscrypt_inode_uses_inline_crypto(const struct inode *inode) +{ + return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && + inode->i_crypt_info->ci_inline_crypt_key != NULL; +} +EXPORT_SYMBOL_GPL(fscrypt_inode_uses_inline_crypto); + +/** + * fscrypt_inode_uses_fs_layer_crypto - test whether an inode uses fs-layer encryption + * @inode: an inode + * + * Return: true if the inode requires file contents encryption and if the + * encryption should be done in the filesystem layer rather than in the + * block layer via blk-crypto. + */ +bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode) +{ + return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && + inode->i_crypt_info->ci_inline_crypt_key == NULL; +} +EXPORT_SYMBOL_GPL(fscrypt_inode_uses_fs_layer_crypto); + +static inline u64 fscrypt_generate_dun(const struct fscrypt_info *ci, + u64 lblk_num) +{ + union fscrypt_iv iv; + + fscrypt_generate_iv(&iv, lblk_num, ci); + /* + * fscrypt_should_use_inline_encryption() ensures we never get here if + * more than the first 8 bytes of the IV are nonzero. + */ + BUG_ON(memchr_inv(&iv.raw[8], 0, ci->ci_mode->ivsize - 8)); + return le64_to_cpu(iv.lblk_num); +} + +/** + * fscrypt_set_bio_crypt_ctx - prepare a file contents bio for inline encryption + * @bio: a bio which will eventually be submitted to the file + * @inode: the file's inode + * @first_lblk: the first file logical block number in the I/O + * @gfp_mask: memory allocation flags + * + * If the contents of the file should be encrypted (or decrypted) with inline + * encryption, then assign the appropriate encryption context to the bio. + * + * Normally the bio should be newly allocated (i.e. no pages added yet), as + * otherwise fscrypt_mergeable_bio() won't work as intended. + * + * The encryption context will be freed automatically when the bio is freed. + * + * Return: 0 on success, -errno on failure. If __GFP_NOFAIL is specified, this + * is guaranteed to succeed. + */ +int fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, + u64 first_lblk, gfp_t gfp_mask) +{ + const struct fscrypt_info *ci = inode->i_crypt_info; + u64 dun; + + if (!fscrypt_inode_uses_inline_crypto(inode)) + return 0; + + dun = fscrypt_generate_dun(ci, first_lblk); + + return bio_crypt_set_ctx(bio, ci->ci_inline_crypt_key, + ci->ci_mode->blk_crypto_mode, + dun, inode->i_blkbits, gfp_mask); +} +EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx); + +/* Extract the inode and logical block number from a buffer_head. */ +static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh, + const struct inode **inode_ret, + u64 *lblk_num_ret) +{ + struct page *page = bh->b_page; + const struct address_space *mapping; + const struct inode *inode; + + /* + * The ext4 journal (jbd2) can submit a buffer_head it directly created + * for a non-pagecache page. fscrypt doesn't care about these. + */ + mapping = page_mapping(page); + if (!mapping) + return false; + inode = mapping->host; + + *inode_ret = inode; + *lblk_num_ret = ((u64)page->index << (PAGE_SHIFT - inode->i_blkbits)) + + (bh_offset(bh) >> inode->i_blkbits); + return true; +} + +/** + * fscrypt_set_bio_crypt_ctx_bh - prepare a file contents bio for inline encryption + * @bio: a bio which will eventually be submitted to the file + * @first_bh: the first buffer_head for which I/O will be submitted + * @gfp_mask: memory allocation flags + * + * Same as fscrypt_set_bio_crypt_ctx(), except this takes a buffer_head instead + * of an inode and block number directly. + * + * Return: 0 on success, -errno on failure + */ +int fscrypt_set_bio_crypt_ctx_bh(struct bio *bio, + const struct buffer_head *first_bh, + gfp_t gfp_mask) +{ + const struct inode *inode; + u64 first_lblk; + + if (!bh_get_inode_and_lblk_num(first_bh, &inode, &first_lblk)) + return 0; + + return fscrypt_set_bio_crypt_ctx(bio, inode, first_lblk, gfp_mask); +} +EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh); + +/** + * fscrypt_mergeable_bio - test whether data can be added to a bio + * @bio: the bio being built up + * @inode: the inode for the next part of the I/O + * @next_lblk: the next file logical block number in the I/O + * + * When building a bio which may contain data which should undergo inline + * encryption (or decryption) via fscrypt, filesystems should call this function + * to ensure that the resulting bio contains only logically contiguous data. + * This will return false if the next part of the I/O cannot be merged with the + * bio because either the encryption key would be different or the encryption + * data unit numbers would be discontiguous. + * + * fscrypt_set_bio_crypt_ctx() must have already been called on the bio. + * + * Return: true iff the I/O is mergeable + */ +bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, + u64 next_lblk) +{ + const struct bio_crypt_ctx *bc; + const u8 *next_key; + u64 next_dun; + + if (bio_has_crypt_ctx(bio) != fscrypt_inode_uses_inline_crypto(inode)) + return false; + if (!bio_has_crypt_ctx(bio)) + return true; + bc = bio->bi_crypt_context; + next_key = inode->i_crypt_info->ci_inline_crypt_key; + next_dun = fscrypt_generate_dun(inode->i_crypt_info, next_lblk); + + /* + * Comparing the key pointers is good enough, as all I/O for each key + * uses the same pointer. I.e., there's currently no need to support + * merging requests where the keys are the same but the pointers differ. + */ + return next_key == bc->raw_key && + next_dun == bc->data_unit_num + + (bio_sectors(bio) >> + (bc->data_unit_size_bits - SECTOR_SHIFT)); +} +EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); + +/** + * fscrypt_mergeable_bio_bh - test whether data can be added to a bio + * @bio: the bio being built up + * @next_bh: the next buffer_head for which I/O will be submitted + * + * Same as fscrypt_mergeable_bio(), except this takes a buffer_head instead of + * an inode and block number directly. + * + * Return: true iff the I/O is mergeable + */ +bool fscrypt_mergeable_bio_bh(struct bio *bio, + const struct buffer_head *next_bh) +{ + const struct inode *inode; + u64 next_lblk; + + if (!bh_get_inode_and_lblk_num(next_bh, &inode, &next_lblk)) + return !bio_has_crypt_ctx(bio); + + return fscrypt_mergeable_bio(bio, inode, next_lblk); +} +EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh); diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index c34fa7c61b43b0cffd18f6db6a9f394c95415799..05cc274e5c136a92563b3b8acde34a885683b108 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -43,8 +43,12 @@ static void free_master_key(struct fscrypt_master_key *mk) wipe_master_key_secret(&mk->mk_secret); - for (i = 0; i < ARRAY_SIZE(mk->mk_mode_keys); i++) - crypto_free_skcipher(mk->mk_mode_keys[i]); + for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) { + crypto_free_skcipher(mk->mk_direct_tfms[i]); + crypto_free_skcipher(mk->mk_iv_ino_lblk_64_tfms[i]); + } + + fscrypt_evict_inline_crypt_keys(mk); key_put(mk->mk_users); kzfree(mk); @@ -704,12 +708,34 @@ static int check_for_busy_inodes(struct super_block *sb, return -EBUSY; } +static BLOCKING_NOTIFIER_HEAD(fscrypt_key_removal_notifiers); + +/* + * Register a function to be executed when the FS_IOC_REMOVE_ENCRYPTION_KEY + * ioctl has removed a key and is about to try evicting inodes. + */ +int fscrypt_register_key_removal_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&fscrypt_key_removal_notifiers, + nb); +} +EXPORT_SYMBOL_GPL(fscrypt_register_key_removal_notifier); + +int fscrypt_unregister_key_removal_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&fscrypt_key_removal_notifiers, + nb); +} +EXPORT_SYMBOL_GPL(fscrypt_unregister_key_removal_notifier); + static int try_to_lock_encrypted_files(struct super_block *sb, struct fscrypt_master_key *mk) { int err1; int err2; + blocking_notifier_call_chain(&fscrypt_key_removal_notifiers, 0, NULL); + /* * An inode can't be evicted while it is dirty or has dirty pages. * Thus, we first have to clean the inodes in ->mk_decrypted_inodes. diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index d71c2d6dd162a4f3195bcfea873f6514bbaa256c..8070dad9a541c5f2b807abbd3270f304b0b3decd 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -8,21 +8,18 @@ * Heavily modified since then. */ -#include -#include #include #include #include "fscrypt_private.h" -static struct crypto_shash *essiv_hash_tfm; - -static struct fscrypt_mode available_modes[] = { +struct fscrypt_mode fscrypt_modes[] = { [FSCRYPT_MODE_AES_256_XTS] = { .friendly_name = "AES-256-XTS", .cipher_str = "xts(aes)", .keysize = 64, .ivsize = 16, + .blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_256_XTS, }, [FSCRYPT_MODE_AES_256_CTS] = { .friendly_name = "AES-256-CTS-CBC", @@ -31,11 +28,10 @@ static struct fscrypt_mode available_modes[] = { .ivsize = 16, }, [FSCRYPT_MODE_AES_128_CBC] = { - .friendly_name = "AES-128-CBC", - .cipher_str = "cbc(aes)", + .friendly_name = "AES-128-CBC-ESSIV", + .cipher_str = "essiv(cbc(aes),sha256)", .keysize = 16, .ivsize = 16, - .needs_essiv = true, }, [FSCRYPT_MODE_AES_128_CTS] = { .friendly_name = "AES-128-CTS-CBC", @@ -56,10 +52,10 @@ select_encryption_mode(const union fscrypt_policy *policy, const struct inode *inode) { if (S_ISREG(inode->i_mode)) - return &available_modes[fscrypt_policy_contents_mode(policy)]; + return &fscrypt_modes[fscrypt_policy_contents_mode(policy)]; if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - return &available_modes[fscrypt_policy_fnames_mode(policy)]; + return &fscrypt_modes[fscrypt_policy_fnames_mode(policy)]; WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", inode->i_ino, (inode->i_mode & S_IFMT)); @@ -111,131 +107,67 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, return ERR_PTR(err); } -static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) -{ - struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm); - - /* init hash transform on demand */ - if (unlikely(!tfm)) { - struct crypto_shash *prev_tfm; - - tfm = crypto_alloc_shash("sha256", 0, 0); - if (IS_ERR(tfm)) { - if (PTR_ERR(tfm) == -ENOENT) { - fscrypt_warn(NULL, - "Missing crypto API support for SHA-256"); - return -ENOPKG; - } - fscrypt_err(NULL, - "Error allocating SHA-256 transform: %ld", - PTR_ERR(tfm)); - return PTR_ERR(tfm); - } - prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm); - if (prev_tfm) { - crypto_free_shash(tfm); - tfm = prev_tfm; - } - } - - { - SHASH_DESC_ON_STACK(desc, tfm); - desc->tfm = tfm; - - return crypto_shash_digest(desc, key, keysize, salt); - } -} - -static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key, - int keysize) -{ - int err; - struct crypto_cipher *essiv_tfm; - u8 salt[SHA256_DIGEST_SIZE]; - - if (WARN_ON(ci->ci_mode->ivsize != AES_BLOCK_SIZE)) - return -EINVAL; - - essiv_tfm = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(essiv_tfm)) - return PTR_ERR(essiv_tfm); - - ci->ci_essiv_tfm = essiv_tfm; - - err = derive_essiv_salt(raw_key, keysize, salt); - if (err) - goto out; - - /* - * Using SHA256 to derive the salt/key will result in AES-256 being - * used for IV generation. File contents encryption will still use the - * configured keysize (AES-128) nevertheless. - */ - err = crypto_cipher_setkey(essiv_tfm, salt, sizeof(salt)); - if (err) - goto out; - -out: - memzero_explicit(salt, sizeof(salt)); - return err; -} - -/* Given the per-file key, set up the file's crypto transform object(s) */ +/* Given the per-file key, set up the file's crypto transform object */ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) { - struct fscrypt_mode *mode = ci->ci_mode; - struct crypto_skcipher *ctfm; - int err; + struct crypto_skcipher *tfm; - ctfm = fscrypt_allocate_skcipher(mode, derived_key, ci->ci_inode); - if (IS_ERR(ctfm)) - return PTR_ERR(ctfm); + if (fscrypt_should_use_inline_encryption(ci)) + return fscrypt_set_inline_crypt_key(ci, derived_key); - ci->ci_ctfm = ctfm; + tfm = fscrypt_allocate_skcipher(ci->ci_mode, derived_key, ci->ci_inode); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); - if (mode->needs_essiv) { - err = init_essiv_generator(ci, derived_key, mode->keysize); - if (err) { - fscrypt_warn(ci->ci_inode, - "Error initializing ESSIV generator: %d", - err); - return err; - } - } + ci->ci_ctfm = tfm; + ci->ci_owns_key = true; return 0; } static int setup_per_mode_key(struct fscrypt_info *ci, - struct fscrypt_master_key *mk) + struct fscrypt_master_key *mk, + struct crypto_skcipher **tfms, + u8 hkdf_context, bool include_fs_uuid) { + const struct inode *inode = ci->ci_inode; + const struct super_block *sb = inode->i_sb; struct fscrypt_mode *mode = ci->ci_mode; - u8 mode_num = mode - available_modes; + const u8 mode_num = mode - fscrypt_modes; struct crypto_skcipher *tfm, *prev_tfm; u8 mode_key[FSCRYPT_MAX_KEY_SIZE]; + u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)]; + unsigned int hkdf_infolen = 0; int err; - if (WARN_ON(mode_num >= ARRAY_SIZE(mk->mk_mode_keys))) + if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX)) return -EINVAL; /* pairs with cmpxchg() below */ - tfm = READ_ONCE(mk->mk_mode_keys[mode_num]); + tfm = READ_ONCE(tfms[mode_num]); if (likely(tfm != NULL)) goto done; BUILD_BUG_ON(sizeof(mode_num) != 1); + BUILD_BUG_ON(sizeof(sb->s_uuid) != 16); + BUILD_BUG_ON(sizeof(hkdf_info) != 17); + hkdf_info[hkdf_infolen++] = mode_num; + if (include_fs_uuid) { + memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid, + sizeof(sb->s_uuid)); + hkdf_infolen += sizeof(sb->s_uuid); + } err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, - HKDF_CONTEXT_PER_MODE_KEY, - &mode_num, sizeof(mode_num), + hkdf_context, hkdf_info, hkdf_infolen, mode_key, mode->keysize); if (err) return err; - tfm = fscrypt_allocate_skcipher(mode, mode_key, ci->ci_inode); + tfm = fscrypt_allocate_skcipher(mode, mode_key, inode); memzero_explicit(mode_key, mode->keysize); if (IS_ERR(tfm)) return PTR_ERR(tfm); /* pairs with READ_ONCE() above */ - prev_tfm = cmpxchg(&mk->mk_mode_keys[mode_num], NULL, tfm); + prev_tfm = cmpxchg(&tfms[mode_num], NULL, tfm); if (prev_tfm != NULL) { crypto_free_skcipher(tfm); tfm = prev_tfm; @@ -266,7 +198,21 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, ci->ci_mode->friendly_name); return -EINVAL; } - return setup_per_mode_key(ci, mk); + return setup_per_mode_key(ci, mk, mk->mk_direct_tfms, + HKDF_CONTEXT_DIRECT_KEY, false); + } else if (ci->ci_policy.v2.flags & + FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { + /* + * IV_INO_LBLK_64: encryption keys are derived from (master_key, + * mode_num, filesystem_uuid), and inode number is included in + * the IVs. This format is optimized for use with inline + * encryption hardware compliant with the UFS or eMMC standards. + */ + if (fscrypt_should_use_inline_encryption(ci)) + return fscrypt_setup_per_mode_inline_crypt_key(ci, mk); + return setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms, + HKDF_CONTEXT_IV_INO_LBLK_64_KEY, + true); } err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, @@ -388,12 +334,11 @@ static void put_crypt_info(struct fscrypt_info *ci) if (!ci) return; - if (ci->ci_direct_key) { + if (ci->ci_direct_key) fscrypt_put_direct_key(ci->ci_direct_key); - } else if ((ci->ci_ctfm != NULL || ci->ci_essiv_tfm != NULL) && - !fscrypt_is_direct_key_policy(&ci->ci_policy)) { + else if (ci->ci_owns_key) { crypto_free_skcipher(ci->ci_ctfm); - crypto_free_cipher(ci->ci_essiv_tfm); + fscrypt_free_inline_crypt_key(ci); } key = ci->ci_master_key; @@ -415,6 +360,7 @@ static void put_crypt_info(struct fscrypt_info *ci) key_invalidate(key); key_put(key); } + memzero_explicit(ci, sizeof(*ci)); kmem_cache_free(fscrypt_info_cachep, ci); } diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c index ad1a36c370c3fb70b62d114ec7896c0d9073f11c..5298ef22aa8598c849981b45cfa7b5cff799861a 100644 --- a/fs/crypto/keysetup_v1.c +++ b/fs/crypto/keysetup_v1.c @@ -270,10 +270,6 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci, return -EINVAL; } - /* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */ - if (WARN_ON(mode->needs_essiv)) - return -EINVAL; - dk = fscrypt_get_direct_key(ci, raw_master_key); if (IS_ERR(dk)) return PTR_ERR(dk); diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 4072ba644595b917ccd128a8ffc5b145513582a0..96f528071bed3f8ea401e38b90ae622d7a261745 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -29,6 +29,40 @@ bool fscrypt_policies_equal(const union fscrypt_policy *policy1, return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); } +static bool supported_iv_ino_lblk_64_policy( + const struct fscrypt_policy_v2 *policy, + const struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + int ino_bits = 64, lblk_bits = 64; + + if (policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { + fscrypt_warn(inode, + "The DIRECT_KEY and IV_INO_LBLK_64 flags are mutually exclusive"); + return false; + } + /* + * It's unsafe to include inode numbers in the IVs if the filesystem can + * potentially renumber inodes, e.g. via filesystem shrinking. + */ + if (!sb->s_cop->has_stable_inodes || + !sb->s_cop->has_stable_inodes(sb)) { + fscrypt_warn(inode, + "Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't have stable inode numbers", + sb->s_id); + return false; + } + if (sb->s_cop->get_ino_and_lblk_bits) + sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits); + if (ino_bits > 32 || lblk_bits > 32) { + fscrypt_warn(inode, + "Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't use 32-bit inode and block numbers", + sb->s_id); + return false; + } + return true; +} + /** * fscrypt_supported_policy - check whether an encryption policy is supported * @@ -55,7 +89,8 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, return false; } - if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) { + if (policy->flags & ~(FSCRYPT_POLICY_FLAGS_PAD_MASK | + FSCRYPT_POLICY_FLAG_DIRECT_KEY)) { fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)", policy->flags); @@ -83,6 +118,10 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, return false; } + if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) && + !supported_iv_ino_lblk_64_policy(policy, inode)) + return false; + if (memchr_inv(policy->__reserved, 0, sizeof(policy->__reserved))) { fscrypt_warn(inode, diff --git a/fs/dax.c b/fs/dax.c index 6bf81f931de39e48bc2983a1c901b1a6643443f8..2cc43cd914eb8332e3c1ccbdcfafa2e6ce64baee 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -220,10 +220,11 @@ static void *get_unlocked_entry(struct xa_state *xas, unsigned int order) for (;;) { entry = xas_find_conflict(xas); + if (!entry || WARN_ON_ONCE(!xa_is_value(entry))) + return entry; if (dax_entry_order(entry) < order) return XA_RETRY_ENTRY; - if (!entry || WARN_ON_ONCE(!xa_is_value(entry)) || - !dax_is_locked(entry)) + if (!dax_is_locked(entry)) return entry; wq = dax_entry_waitqueue(xas, entry, &ewait.key); diff --git a/fs/direct-io.c b/fs/direct-io.c index ae196784f487afa9a4117e0775d42559645d4b73..9329ced91f1d8563010dc45a9be430e62ba659d6 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -241,9 +241,8 @@ void dio_warn_stale_pagecache(struct file *filp) } } -/** +/* * dio_complete() - called when all DIO BIO I/O has been completed - * @offset: the byte offset in the file of the completed operation * * This drops i_dio_count, lets interested parties know that a DIO operation * has completed, and calculates the resulting return code for the operation. diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 03db3e71676ce1d79a65761f102c4bef6660d01e..ce493e360814453b260544d14f9fe960a1a922bc 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1148,6 +1148,7 @@ struct ext4_inode_info { #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ #define EXT4_MOUNT_WARN_ON_ERROR 0x2000000 /* Trigger WARN_ON on error */ +#define EXT4_MOUNT_INLINECRYPT 0x4000000 /* Inline encryption support */ #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ @@ -1678,6 +1679,7 @@ static inline bool ext4_verity_in_progress(struct inode *inode) #define EXT4_FEATURE_COMPAT_RESIZE_INODE 0x0010 #define EXT4_FEATURE_COMPAT_DIR_INDEX 0x0020 #define EXT4_FEATURE_COMPAT_SPARSE_SUPER2 0x0200 +#define EXT4_FEATURE_COMPAT_STABLE_INODES 0x0800 #define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 #define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 @@ -1779,6 +1781,7 @@ EXT4_FEATURE_COMPAT_FUNCS(xattr, EXT_ATTR) EXT4_FEATURE_COMPAT_FUNCS(resize_inode, RESIZE_INODE) EXT4_FEATURE_COMPAT_FUNCS(dir_index, DIR_INDEX) EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, SPARSE_SUPER2) +EXT4_FEATURE_COMPAT_FUNCS(stable_inodes, STABLE_INODES) EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super, SPARSE_SUPER) EXT4_FEATURE_RO_COMPAT_FUNCS(large_file, LARGE_FILE) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ac409eb63100ddf3e88a2e408a180e6686464653..a32c8755b6da5801c1455d4fb714b2ea465b5d37 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1238,7 +1238,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, } if (unlikely(err)) { page_zero_new_buffers(page, from, to); - } else if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) { + } else if (fscrypt_inode_uses_fs_layer_crypto(inode)) { for (i = 0; i < nr_wait; i++) { int err2; @@ -4089,7 +4089,7 @@ static int __ext4_block_zero_page_range(handle_t *handle, /* Uhhuh. Read error. Complain and punt. */ if (!buffer_uptodate(bh)) goto unlock; - if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) { + if (fscrypt_inode_uses_fs_layer_crypto(inode)) { /* We expect the key to be set. */ BUG_ON(!fscrypt_has_encryption_key(inode)); WARN_ON_ONCE(fscrypt_decrypt_pagecache_blocks( diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 12ceadef32c5a393a7588f80067418f20bc1e10d..46a4aeef8275452101217f8ab45d298d48865bc3 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -362,10 +362,16 @@ static int io_submit_init_bio(struct ext4_io_submit *io, struct buffer_head *bh) { struct bio *bio; + int err; bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); if (!bio) return -ENOMEM; + err = fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO); + if (err) { + bio_put(bio); + return err; + } bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio_set_dev(bio, bh->b_bdev); bio->bi_end_io = ext4_end_bio; @@ -383,7 +389,8 @@ static int io_submit_add_bh(struct ext4_io_submit *io, { int ret; - if (io->io_bio && bh->b_blocknr != io->io_next_block) { + if (io->io_bio && (bh->b_blocknr != io->io_next_block || + !fscrypt_mergeable_bio_bh(io->io_bio, bh))) { submit_and_retry: ext4_io_submit(io); } @@ -474,7 +481,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, * (e.g. holes) to be unnecessarily encrypted, but this is rare and * can't happen in the common case of blocksize == PAGE_SIZE. */ - if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode) && nr_to_submit) { + if (fscrypt_inode_uses_fs_layer_crypto(inode) && nr_to_submit) { gfp_t gfp_flags = GFP_NOFS; unsigned int enc_bytes = round_up(len, i_blocksize(inode)); diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index 0d88b82a59290312e1539bdc63e811e5d3fb4c45..e21216e7ae241c3806111317d2f4d4e13cfb3fd3 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -198,7 +198,7 @@ static struct bio_post_read_ctx *get_bio_post_read_ctx(struct inode *inode, unsigned int post_read_steps = 0; struct bio_post_read_ctx *ctx = NULL; - if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) + if (fscrypt_inode_uses_fs_layer_crypto(inode)) post_read_steps |= 1 << STEP_DECRYPT; if (ext4_need_verity(inode, first_idx)) @@ -259,6 +259,7 @@ int ext4_mpage_readpages(struct address_space *mapping, const unsigned blkbits = inode->i_blkbits; const unsigned blocks_per_page = PAGE_SIZE >> blkbits; const unsigned blocksize = 1 << blkbits; + sector_t next_block; sector_t block_in_file; sector_t last_block; sector_t last_block_in_file; @@ -291,7 +292,8 @@ int ext4_mpage_readpages(struct address_space *mapping, if (page_has_buffers(page)) goto confused; - block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits); + block_in_file = next_block = + (sector_t)page->index << (PAGE_SHIFT - blkbits); last_block = block_in_file + nr_pages * blocks_per_page; last_block_in_file = (ext4_readpage_limit(inode) + blocksize - 1) >> blkbits; @@ -391,7 +393,8 @@ int ext4_mpage_readpages(struct address_space *mapping, * This page will go to BIO. Do we need to send this * BIO off first? */ - if (bio && (last_block_in_bio != blocks[0] - 1)) { + if (bio && (last_block_in_bio != blocks[0] - 1 || + !fscrypt_mergeable_bio(bio, inode, next_block))) { submit_and_realloc: ext4_submit_bio_read(bio); bio = NULL; @@ -403,6 +406,12 @@ int ext4_mpage_readpages(struct address_space *mapping, min_t(int, nr_pages, BIO_MAX_PAGES)); if (!bio) goto set_error_page; + if (fscrypt_set_bio_crypt_ctx(bio, inode, next_block, + GFP_KERNEL) != 0) { + bio_put(bio); + bio = NULL; + goto set_error_page; + } ctx = get_bio_post_read_ctx(inode, bio, page->index); if (IS_ERR(ctx)) { bio_put(bio); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index dd654e53ba3d982d99c05b2336dd4de9132b0978..3415bce51a3637c2084a1afecc84854668451e16 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1345,6 +1345,23 @@ static bool ext4_dummy_context(struct inode *inode) return DUMMY_ENCRYPTION_ENABLED(EXT4_SB(inode->i_sb)); } +static bool ext4_has_stable_inodes(struct super_block *sb) +{ + return ext4_has_feature_stable_inodes(sb); +} + +static void ext4_get_ino_and_lblk_bits(struct super_block *sb, + int *ino_bits_ret, int *lblk_bits_ret) +{ + *ino_bits_ret = 8 * sizeof(EXT4_SB(sb)->s_es->s_inodes_count); + *lblk_bits_ret = 8 * sizeof(ext4_lblk_t); +} + +static bool ext4_inline_crypt_enabled(struct super_block *sb) +{ + return test_opt(sb, INLINECRYPT); +} + static const struct fscrypt_operations ext4_cryptops = { .key_prefix = "ext4:", .get_context = ext4_get_context, @@ -1352,6 +1369,9 @@ static const struct fscrypt_operations ext4_cryptops = { .dummy_context = ext4_dummy_context, .empty_dir = ext4_empty_dir, .max_namelen = EXT4_NAME_LEN, + .has_stable_inodes = ext4_has_stable_inodes, + .get_ino_and_lblk_bits = ext4_get_ino_and_lblk_bits, + .inline_crypt_enabled = ext4_inline_crypt_enabled, }; #endif @@ -1447,6 +1467,7 @@ enum { Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit, Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption, + Opt_inlinecrypt, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, @@ -1543,6 +1564,7 @@ static const match_table_t tokens = { {Opt_noinit_itable, "noinit_itable"}, {Opt_max_dir_size_kb, "max_dir_size_kb=%u"}, {Opt_test_dummy_encryption, "test_dummy_encryption"}, + {Opt_inlinecrypt, "inlinecrypt"}, {Opt_nombcache, "nombcache"}, {Opt_nombcache, "no_mbcache"}, /* for backward compatibility */ {Opt_removed, "check=none"}, /* mount option from ext2/3 */ @@ -1754,6 +1776,11 @@ static const struct mount_opts { {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT}, {Opt_max_dir_size_kb, 0, MOPT_GTE0}, {Opt_test_dummy_encryption, 0, MOPT_GTE0}, +#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT + {Opt_inlinecrypt, EXT4_MOUNT_INLINECRYPT, MOPT_SET}, +#else + {Opt_inlinecrypt, EXT4_MOUNT_INLINECRYPT, MOPT_NOSUPPORT}, +#endif {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET}, {Opt_err, 0, 0} }; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 9155256779bf8fcac93d2af4a0b417dae78439dc..f981bb4a18b86bdb43e9354e330b6226d8c6e98b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -307,6 +307,35 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) return bio; } +static int f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, + pgoff_t first_idx, + const struct f2fs_io_info *fio, + gfp_t gfp_mask) +{ + /* + * The f2fs garbage collector sets ->encrypted_page when it wants to + * read/write raw data without encryption. + */ + if (fio && fio->encrypted_page) + return 0; + + return fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask); +} + +static bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode, + pgoff_t next_idx, + const struct f2fs_io_info *fio) +{ + /* + * The f2fs garbage collector sets ->encrypted_page when it wants to + * read/write raw data without encryption. + */ + if (fio && fio->encrypted_page) + return true; + + return fscrypt_mergeable_bio(bio, inode, next_idx); +} + static inline void __submit_bio(struct f2fs_sb_info *sbi, struct bio *bio, enum page_type type) { @@ -478,6 +507,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) struct bio *bio; struct page *page = fio->encrypted_page ? fio->encrypted_page : fio->page; + int err; if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, fio->is_por ? META_POR : (__is_meta_io(fio) ? @@ -490,6 +520,13 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) /* Allocate a new bio */ bio = __bio_alloc(fio, 1); + err = f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, + fio->page->index, fio, GFP_NOIO); + if (err) { + bio_put(bio); + return err; + } + if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); return -EFAULT; @@ -557,14 +594,19 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) trace_f2fs_submit_page_bio(page, fio); f2fs_trace_ios(fio, 0); - if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block, - fio->new_blkaddr)) { + if (bio && (!page_is_mergeable(fio->sbi, bio, *fio->last_block, + fio->new_blkaddr) || + !f2fs_crypt_mergeable_bio(bio, fio->page->mapping->host, + fio->page->index, fio))) { __submit_bio(fio->sbi, bio, fio->type); bio = NULL; } alloc_new: if (!bio) { bio = __bio_alloc(fio, BIO_MAX_PAGES); + f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, + fio->page->index, fio, + GFP_NOIO | __GFP_NOFAIL); bio_set_op_attrs(bio, fio->op, fio->op_flags); } @@ -630,8 +672,11 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) inc_page_count(sbi, WB_DATA_TYPE(bio_page)); - if (io->bio && !io_is_mergeable(sbi, io->bio, io, fio, - io->last_block_in_bio, fio->new_blkaddr)) + if (io->bio && + (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, + fio->new_blkaddr) || + !f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host, + fio->page->index, fio))) __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { @@ -643,6 +688,9 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) goto skip; } io->bio = __bio_alloc(fio, BIO_MAX_PAGES); + f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, + fio->page->index, fio, + GFP_NOIO | __GFP_NOFAIL); io->fio = *fio; } @@ -682,15 +730,23 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, struct bio *bio; struct bio_post_read_ctx *ctx; unsigned int post_read_steps = 0; + int err; bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false); if (!bio) return ERR_PTR(-ENOMEM); + + err = f2fs_set_bio_crypt_ctx(bio, inode, first_idx, NULL, GFP_NOFS); + if (err) { + bio_put(bio); + return ERR_PTR(err); + } + f2fs_target_device(sbi, blkaddr, bio); bio->bi_end_io = f2fs_read_end_io; bio_set_op_attrs(bio, REQ_OP_READ, op_flag); - if (f2fs_encrypted_file(inode)) + if (fscrypt_inode_uses_fs_layer_crypto(inode)) post_read_steps |= 1 << STEP_DECRYPT; if (f2fs_need_verity(inode, first_idx)) @@ -1727,8 +1783,9 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, * This page will go to BIO. Do we need to send this * BIO off first? */ - if (bio && !page_is_mergeable(F2FS_I_SB(inode), bio, - *last_block_in_bio, block_nr)) { + if (bio && (!page_is_mergeable(F2FS_I_SB(inode), bio, + *last_block_in_bio, block_nr) || + !f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) { submit_and_realloc: __submit_bio(F2FS_I_SB(inode), bio, DATA); bio = NULL; @@ -1868,6 +1925,9 @@ static int encrypt_one_page(struct f2fs_io_info *fio) /* wait for GCed page writeback via META_MAPPING */ f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); + if (fscrypt_inode_uses_inline_crypto(inode)) + return 0; + retry_encrypt: fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(fio->page, PAGE_SIZE, 0, @@ -2042,7 +2102,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) f2fs_unlock_op(fio->sbi); err = f2fs_inplace_write_data(fio); if (err) { - if (f2fs_encrypted_file(inode)) + if (fscrypt_inode_uses_fs_layer_crypto(inode)) fscrypt_finalize_bounce_page(&fio->encrypted_page); if (PageWriteback(page)) end_page_writeback(page); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4024790028aab1ecdc1d984b9bb724da31de7125..e04fda00b4efbef2e8f70c265a02105e61bec168 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -137,6 +137,9 @@ struct f2fs_mount_info { int alloc_mode; /* segment allocation policy */ int fsync_mode; /* fsync policy */ bool test_dummy_encryption; /* test dummy encryption */ +#ifdef CONFIG_FS_ENCRYPTION + bool inlinecrypt; /* inline encryption enabled */ +#endif block_t unusable_cap; /* Amount of space allowed to be * unusable when disabling checkpoint */ diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1443cee158633d01b6b1dfee3538bde13c4860b8..850a2a2394d8558c6177f8ddb6ba75fb472e18c4 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -137,6 +137,7 @@ enum { Opt_alloc, Opt_fsync, Opt_test_dummy_encryption, + Opt_inlinecrypt, Opt_checkpoint_disable, Opt_checkpoint_disable_cap, Opt_checkpoint_disable_cap_perc, @@ -199,6 +200,7 @@ static match_table_t f2fs_tokens = { {Opt_alloc, "alloc_mode=%s"}, {Opt_fsync, "fsync_mode=%s"}, {Opt_test_dummy_encryption, "test_dummy_encryption"}, + {Opt_inlinecrypt, "inlinecrypt"}, {Opt_checkpoint_disable, "checkpoint=disable"}, {Opt_checkpoint_disable_cap, "checkpoint=disable:%u"}, {Opt_checkpoint_disable_cap_perc, "checkpoint=disable:%u%%"}, @@ -783,6 +785,13 @@ static int parse_options(struct super_block *sb, char *options) f2fs_info(sbi, "Test dummy encryption mode enabled"); #else f2fs_info(sbi, "Test dummy encryption mount option ignored"); +#endif + break; + case Opt_inlinecrypt: +#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT + F2FS_OPTION(sbi).inlinecrypt = true; +#else + f2fs_info(sbi, "inline encryption not supported"); #endif break; case Opt_checkpoint_disable_cap_perc: @@ -1438,6 +1447,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) #ifdef CONFIG_FS_ENCRYPTION if (F2FS_OPTION(sbi).test_dummy_encryption) seq_puts(seq, ",test_dummy_encryption"); + if (F2FS_OPTION(sbi).inlinecrypt) + seq_puts(seq, ",inlinecrypt"); #endif if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT) @@ -1466,6 +1477,9 @@ static void default_options(struct f2fs_sb_info *sbi) F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT; F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX; F2FS_OPTION(sbi).test_dummy_encryption = false; +#ifdef CONFIG_FS_ENCRYPTION + F2FS_OPTION(sbi).inlinecrypt = false; +#endif F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID); F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID); @@ -2308,13 +2322,33 @@ static bool f2fs_dummy_context(struct inode *inode) return DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(inode)); } +static bool f2fs_has_stable_inodes(struct super_block *sb) +{ + return true; +} + +static void f2fs_get_ino_and_lblk_bits(struct super_block *sb, + int *ino_bits_ret, int *lblk_bits_ret) +{ + *ino_bits_ret = 8 * sizeof(nid_t); + *lblk_bits_ret = 8 * sizeof(block_t); +} + +static bool f2fs_inline_crypt_enabled(struct super_block *sb) +{ + return F2FS_OPTION(F2FS_SB(sb)).inlinecrypt; +} + static const struct fscrypt_operations f2fs_cryptops = { - .key_prefix = "f2fs:", - .get_context = f2fs_get_context, - .set_context = f2fs_set_context, - .dummy_context = f2fs_dummy_context, - .empty_dir = f2fs_empty_dir, - .max_namelen = F2FS_NAME_LEN, + .key_prefix = "f2fs:", + .get_context = f2fs_get_context, + .set_context = f2fs_set_context, + .dummy_context = f2fs_dummy_context, + .empty_dir = f2fs_empty_dir, + .max_namelen = F2FS_NAME_LEN, + .has_stable_inodes = f2fs_has_stable_inodes, + .get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits, + .inline_crypt_enabled = f2fs_inline_crypt_enabled, }; #endif diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e88421d9a48d44e851ba77724d58e389a9c1db7d..8461a63220398024c2aef5d4795d2f2aadd4ebfa 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -905,7 +905,7 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi, * cgroup_writeback_by_id - initiate cgroup writeback from bdi and memcg IDs * @bdi_id: target bdi id * @memcg_id: target memcg css id - * @nr_pages: number of pages to write, 0 for best-effort dirty flushing + * @nr: number of pages to write, 0 for best-effort dirty flushing * @reason: reason why some writeback work initiated * @done: target wb_completion * diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile index 6419a2b3510deada202d4ccd9a4ca3447f8baa07..3e8cebfb59b7b38155f89196d7b2f2b8e764810b 100644 --- a/fs/fuse/Makefile +++ b/fs/fuse/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_FUSE_FS) += fuse.o obj-$(CONFIG_CUSE) += cuse.o -obj-$(CONFIG_VIRTIO_FS) += virtio_fs.o +obj-$(CONFIG_VIRTIO_FS) += virtiofs.o fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o +virtiofs-y += virtio_fs.o diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index dadd617d826c93825500679f33a524940c15c2e7..ed1abc9e33cfcc165442c11b435f36a294a892a2 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -276,10 +276,12 @@ static void flush_bg_queue(struct fuse_conn *fc) void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) { struct fuse_iqueue *fiq = &fc->iq; - bool async = req->args->end; + bool async; if (test_and_set_bit(FR_FINISHED, &req->flags)) goto put_request; + + async = req->args->end; /* * test_and_set_bit() implies smp_mb() between bit * changing and below intr_entry check. Pairs with diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d572c900bb0f208c6a49a43b97ece1cb882687f7..54d638f9ba1caea3cbd8c539b73204cd60ed19ba 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -405,7 +405,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, else fuse_invalidate_entry_cache(entry); - fuse_advise_use_readdirplus(dir); + if (inode) + fuse_advise_use_readdirplus(dir); return newent; out_iput: @@ -1521,6 +1522,19 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, is_truncate = true; } + /* Flush dirty data/metadata before non-truncate SETATTR */ + if (is_wb && S_ISREG(inode->i_mode) && + attr->ia_valid & + (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET | + ATTR_TIMES_SET)) { + err = write_inode_now(inode, true); + if (err) + return err; + + fuse_set_nowrite(inode); + fuse_release_nowrite(inode); + } + if (is_truncate) { fuse_set_nowrite(inode); set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 0f0225686aeeb2acfbeff178bfd2434e4ea80795..db48a5cf862095160179b7d205c7c8cd8c046c24 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -217,7 +217,7 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) { struct fuse_conn *fc = get_fuse_conn(inode); int err; - bool lock_inode = (file->f_flags & O_TRUNC) && + bool is_wb_truncate = (file->f_flags & O_TRUNC) && fc->atomic_o_trunc && fc->writeback_cache; @@ -225,16 +225,20 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) if (err) return err; - if (lock_inode) + if (is_wb_truncate) { inode_lock(inode); + fuse_set_nowrite(inode); + } err = fuse_do_open(fc, get_node_id(inode), file, isdir); if (!err) fuse_finish_open(inode, file); - if (lock_inode) + if (is_wb_truncate) { + fuse_release_nowrite(inode); inode_unlock(inode); + } return err; } @@ -1997,7 +2001,7 @@ static int fuse_writepages_fill(struct page *page, if (!data->ff) { err = -EIO; - data->ff = fuse_write_file_get(fc, get_fuse_inode(inode)); + data->ff = fuse_write_file_get(fc, fi); if (!data->ff) goto out_unlock; } @@ -2042,8 +2046,6 @@ static int fuse_writepages_fill(struct page *page, * under writeback, so we can release the page lock. */ if (data->wpa == NULL) { - struct fuse_inode *fi = get_fuse_inode(inode); - err = -ENOMEM; wpa = fuse_writepage_args_alloc(); if (!wpa) { diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 956aeaf961ae12b8c52d55fb961f3c18af66293e..d148188cfca453499d46eb6eaa9d77b645474a5a 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -479,6 +479,7 @@ struct fuse_fs_context { bool destroy:1; bool no_control:1; bool no_force_umount:1; + bool no_mount_options:1; unsigned int max_read; unsigned int blksize; const char *subtype; @@ -713,6 +714,9 @@ struct fuse_conn { /** Do not allow MNT_FORCE umount */ unsigned int no_force_umount:1; + /* Do not show mount options */ + unsigned int no_mount_options:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index e040e2a2b62102bdcfbae5b5cf92a1a60996c58d..16aec32f7f3d71767746a886a95e8dfd151d24de 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -558,6 +558,9 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root) struct super_block *sb = root->d_sb; struct fuse_conn *fc = get_fuse_conn_super(sb); + if (fc->no_mount_options) + return 0; + seq_printf(m, ",user_id=%u", from_kuid_munged(fc->user_ns, fc->user_id)); seq_printf(m, ",group_id=%u", from_kgid_munged(fc->user_ns, fc->group_id)); if (fc->default_permissions) @@ -1180,6 +1183,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx) fc->destroy = ctx->destroy; fc->no_control = ctx->no_control; fc->no_force_umount = ctx->no_force_umount; + fc->no_mount_options = ctx->no_mount_options; err = -ENOMEM; root = fuse_get_root_inode(sb, ctx->rootmode); diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 6af3f131e468ad3ee7bedffe41f4bb0b6b03e91c..a5c86048b96edb59f85986935206f2c53972a170 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -30,6 +30,7 @@ struct virtio_fs_vq { struct virtqueue *vq; /* protected by ->lock */ struct work_struct done_work; struct list_head queued_reqs; + struct list_head end_reqs; /* End these requests */ struct delayed_work dispatch_work; struct fuse_dev *fud; bool connected; @@ -54,6 +55,9 @@ struct virtio_fs_forget { struct list_head list; }; +static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, + struct fuse_req *req, bool in_flight); + static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq) { struct virtio_fs *fs = vq->vdev->priv; @@ -66,6 +70,19 @@ static inline struct fuse_pqueue *vq_to_fpq(struct virtqueue *vq) return &vq_to_fsvq(vq)->fud->pq; } +/* Should be called with fsvq->lock held. */ +static inline void inc_in_flight_req(struct virtio_fs_vq *fsvq) +{ + fsvq->in_flight++; +} + +/* Should be called with fsvq->lock held. */ +static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq) +{ + WARN_ON(fsvq->in_flight <= 0); + fsvq->in_flight--; +} + static void release_virtio_fs_obj(struct kref *ref) { struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount); @@ -109,22 +126,6 @@ static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq) flush_delayed_work(&fsvq->dispatch_work); } -static inline void drain_hiprio_queued_reqs(struct virtio_fs_vq *fsvq) -{ - struct virtio_fs_forget *forget; - - spin_lock(&fsvq->lock); - while (1) { - forget = list_first_entry_or_null(&fsvq->queued_reqs, - struct virtio_fs_forget, list); - if (!forget) - break; - list_del(&forget->list); - kfree(forget); - } - spin_unlock(&fsvq->lock); -} - static void virtio_fs_drain_all_queues(struct virtio_fs *fs) { struct virtio_fs_vq *fsvq; @@ -132,9 +133,6 @@ static void virtio_fs_drain_all_queues(struct virtio_fs *fs) for (i = 0; i < fs->nvqs; i++) { fsvq = &fs->vqs[i]; - if (i == VQ_HIPRIO) - drain_hiprio_queued_reqs(fsvq); - virtio_fs_drain_queue(fsvq); } } @@ -253,14 +251,66 @@ static void virtio_fs_hiprio_done_work(struct work_struct *work) while ((req = virtqueue_get_buf(vq, &len)) != NULL) { kfree(req); - fsvq->in_flight--; + dec_in_flight_req(fsvq); } } while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq))); spin_unlock(&fsvq->lock); } -static void virtio_fs_dummy_dispatch_work(struct work_struct *work) +static void virtio_fs_request_dispatch_work(struct work_struct *work) { + struct fuse_req *req; + struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq, + dispatch_work.work); + struct fuse_conn *fc = fsvq->fud->fc; + int ret; + + pr_debug("virtio-fs: worker %s called.\n", __func__); + while (1) { + spin_lock(&fsvq->lock); + req = list_first_entry_or_null(&fsvq->end_reqs, struct fuse_req, + list); + if (!req) { + spin_unlock(&fsvq->lock); + break; + } + + list_del_init(&req->list); + spin_unlock(&fsvq->lock); + fuse_request_end(fc, req); + } + + /* Dispatch pending requests */ + while (1) { + spin_lock(&fsvq->lock); + req = list_first_entry_or_null(&fsvq->queued_reqs, + struct fuse_req, list); + if (!req) { + spin_unlock(&fsvq->lock); + return; + } + list_del_init(&req->list); + spin_unlock(&fsvq->lock); + + ret = virtio_fs_enqueue_req(fsvq, req, true); + if (ret < 0) { + if (ret == -ENOMEM || ret == -ENOSPC) { + spin_lock(&fsvq->lock); + list_add_tail(&req->list, &fsvq->queued_reqs); + schedule_delayed_work(&fsvq->dispatch_work, + msecs_to_jiffies(1)); + spin_unlock(&fsvq->lock); + return; + } + req->out.h.error = ret; + spin_lock(&fsvq->lock); + dec_in_flight_req(fsvq); + spin_unlock(&fsvq->lock); + pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", + ret); + fuse_request_end(fc, req); + } + } } static void virtio_fs_hiprio_dispatch_work(struct work_struct *work) @@ -286,6 +336,7 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work) list_del(&forget->list); if (!fsvq->connected) { + dec_in_flight_req(fsvq); spin_unlock(&fsvq->lock); kfree(forget); continue; @@ -307,13 +358,13 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work) } else { pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n", ret); + dec_in_flight_req(fsvq); kfree(forget); } spin_unlock(&fsvq->lock); return; } - fsvq->in_flight++; notify = virtqueue_kick_prepare(vq); spin_unlock(&fsvq->lock); @@ -452,7 +503,7 @@ static void virtio_fs_requests_done_work(struct work_struct *work) fuse_request_end(fc, req); spin_lock(&fsvq->lock); - fsvq->in_flight--; + dec_in_flight_req(fsvq); spin_unlock(&fsvq->lock); } } @@ -502,6 +553,7 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev, names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name; INIT_WORK(&fs->vqs[VQ_HIPRIO].done_work, virtio_fs_hiprio_done_work); INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].queued_reqs); + INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].end_reqs); INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work, virtio_fs_hiprio_dispatch_work); spin_lock_init(&fs->vqs[VQ_HIPRIO].lock); @@ -511,8 +563,9 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev, spin_lock_init(&fs->vqs[i].lock); INIT_WORK(&fs->vqs[i].done_work, virtio_fs_requests_done_work); INIT_DELAYED_WORK(&fs->vqs[i].dispatch_work, - virtio_fs_dummy_dispatch_work); + virtio_fs_request_dispatch_work); INIT_LIST_HEAD(&fs->vqs[i].queued_reqs); + INIT_LIST_HEAD(&fs->vqs[i].end_reqs); snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name), "requests.%u", i - VQ_REQUEST); callbacks[i] = virtio_fs_vq_done; @@ -708,6 +761,7 @@ __releases(fiq->lock) list_add_tail(&forget->list, &fsvq->queued_reqs); schedule_delayed_work(&fsvq->dispatch_work, msecs_to_jiffies(1)); + inc_in_flight_req(fsvq); } else { pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n", ret); @@ -717,7 +771,7 @@ __releases(fiq->lock) goto out; } - fsvq->in_flight++; + inc_in_flight_req(fsvq); notify = virtqueue_kick_prepare(vq); spin_unlock(&fsvq->lock); @@ -819,7 +873,7 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg, /* Add a request to a virtqueue and kick the device */ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, - struct fuse_req *req) + struct fuse_req *req, bool in_flight) { /* requests need at least 4 elements */ struct scatterlist *stack_sgs[6]; @@ -835,6 +889,7 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, unsigned int i; int ret; bool notify; + struct fuse_pqueue *fpq; /* Does the sglist fit on the stack? */ total_sgs = sg_count_fuse_req(req); @@ -889,7 +944,17 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, goto out; } - fsvq->in_flight++; + /* Request successfully sent. */ + fpq = &fsvq->fud->pq; + spin_lock(&fpq->lock); + list_add_tail(&req->list, fpq->processing); + spin_unlock(&fpq->lock); + set_bit(FR_SENT, &req->flags); + /* matches barrier in request_wait_answer() */ + smp_mb__after_atomic(); + + if (!in_flight) + inc_in_flight_req(fsvq); notify = virtqueue_kick_prepare(vq); spin_unlock(&fsvq->lock); @@ -915,9 +980,8 @@ __releases(fiq->lock) { unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */ struct virtio_fs *fs; - struct fuse_conn *fc; struct fuse_req *req; - struct fuse_pqueue *fpq; + struct virtio_fs_vq *fsvq; int ret; WARN_ON(list_empty(&fiq->pending)); @@ -928,44 +992,36 @@ __releases(fiq->lock) spin_unlock(&fiq->lock); fs = fiq->priv; - fc = fs->vqs[queue_id].fud->fc; pr_debug("%s: opcode %u unique %#llx nodeid %#llx in.len %u out.len %u\n", __func__, req->in.h.opcode, req->in.h.unique, req->in.h.nodeid, req->in.h.len, fuse_len_args(req->args->out_numargs, req->args->out_args)); - fpq = &fs->vqs[queue_id].fud->pq; - spin_lock(&fpq->lock); - if (!fpq->connected) { - spin_unlock(&fpq->lock); - req->out.h.error = -ENODEV; - pr_err("virtio-fs: %s disconnected\n", __func__); - fuse_request_end(fc, req); - return; - } - list_add_tail(&req->list, fpq->processing); - spin_unlock(&fpq->lock); - set_bit(FR_SENT, &req->flags); - /* matches barrier in request_wait_answer() */ - smp_mb__after_atomic(); - -retry: - ret = virtio_fs_enqueue_req(&fs->vqs[queue_id], req); + fsvq = &fs->vqs[queue_id]; + ret = virtio_fs_enqueue_req(fsvq, req, false); if (ret < 0) { if (ret == -ENOMEM || ret == -ENOSPC) { - /* Virtqueue full. Retry submission */ - /* TODO use completion instead of timeout */ - usleep_range(20, 30); - goto retry; + /* + * Virtqueue full. Retry submission from worker + * context as we might be holding fc->bg_lock. + */ + spin_lock(&fsvq->lock); + list_add_tail(&req->list, &fsvq->queued_reqs); + inc_in_flight_req(fsvq); + schedule_delayed_work(&fsvq->dispatch_work, + msecs_to_jiffies(1)); + spin_unlock(&fsvq->lock); + return; } req->out.h.error = ret; pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret); - spin_lock(&fpq->lock); - clear_bit(FR_SENT, &req->flags); - list_del_init(&req->list); - spin_unlock(&fpq->lock); - fuse_request_end(fc, req); + + /* Can't end request in submission context. Use a worker */ + spin_lock(&fsvq->lock); + list_add_tail(&req->list, &fsvq->end_reqs); + schedule_delayed_work(&fsvq->dispatch_work, 0); + spin_unlock(&fsvq->lock); return; } } @@ -992,6 +1048,7 @@ static int virtio_fs_fill_super(struct super_block *sb) .destroy = true, .no_control = true, .no_force_umount = true, + .no_mount_options = true, }; mutex_lock(&virtio_fs_mutex); diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 681b44682b0db6a6016303ec515c291720e6ff32..18daf494abab9e2492ab12272358d151e5c5538a 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1540,17 +1540,23 @@ static int gfs2_init_fs_context(struct fs_context *fc) { struct gfs2_args *args; - args = kzalloc(sizeof(*args), GFP_KERNEL); + args = kmalloc(sizeof(*args), GFP_KERNEL); if (args == NULL) return -ENOMEM; - args->ar_quota = GFS2_QUOTA_DEFAULT; - args->ar_data = GFS2_DATA_DEFAULT; - args->ar_commit = 30; - args->ar_statfs_quantum = 30; - args->ar_quota_quantum = 60; - args->ar_errors = GFS2_ERRORS_DEFAULT; + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { + struct gfs2_sbd *sdp = fc->root->d_sb->s_fs_info; + *args = sdp->sd_args; + } else { + memset(args, 0, sizeof(*args)); + args->ar_quota = GFS2_QUOTA_DEFAULT; + args->ar_data = GFS2_DATA_DEFAULT; + args->ar_commit = 30; + args->ar_statfs_quantum = 30; + args->ar_quota_quantum = 60; + args->ar_errors = GFS2_ERRORS_DEFAULT; + } fc->fs_private = args; fc->ops = &gfs2_context_ops; return 0; @@ -1600,6 +1606,7 @@ static int gfs2_meta_get_tree(struct fs_context *fc) } static const struct fs_context_operations gfs2_meta_context_ops = { + .free = gfs2_fc_free, .get_tree = gfs2_meta_get_tree, }; diff --git a/fs/io_uring.c b/fs/io_uring.c index 76fdbe84aff57348df6c7f3ad59abe951916e055..f9a38998f2fc515c94c4cc292e00450a55aaa912 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -197,6 +197,7 @@ struct io_ring_ctx { unsigned sq_entries; unsigned sq_mask; unsigned sq_thread_idle; + unsigned cached_sq_dropped; struct io_uring_sqe *sq_sqes; struct list_head defer_list; @@ -212,6 +213,7 @@ struct io_ring_ctx { struct { unsigned cached_cq_tail; + atomic_t cached_cq_overflow; unsigned cq_entries; unsigned cq_mask; struct wait_queue_head cq_wait; @@ -322,6 +324,8 @@ struct io_kiocb { #define REQ_F_FAIL_LINK 256 /* fail rest of links */ #define REQ_F_SHADOW_DRAIN 512 /* link-drain shadow req */ #define REQ_F_TIMEOUT 1024 /* timeout request */ +#define REQ_F_ISREG 2048 /* regular file */ +#define REQ_F_MUST_PUNT 4096 /* must be punted even for NONBLOCK */ u64 user_data; u32 result; u32 sequence; @@ -418,7 +422,8 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p) static inline bool __io_sequence_defer(struct io_ring_ctx *ctx, struct io_kiocb *req) { - return req->sequence != ctx->cached_cq_tail + ctx->rings->sq_dropped; + return req->sequence != ctx->cached_cq_tail + ctx->cached_sq_dropped + + atomic_read(&ctx->cached_cq_overflow); } static inline bool io_sequence_defer(struct io_ring_ctx *ctx, @@ -565,9 +570,8 @@ static void io_cqring_fill_event(struct io_ring_ctx *ctx, u64 ki_user_data, WRITE_ONCE(cqe->res, res); WRITE_ONCE(cqe->flags, 0); } else { - unsigned overflow = READ_ONCE(ctx->rings->cq_overflow); - - WRITE_ONCE(ctx->rings->cq_overflow, overflow + 1); + WRITE_ONCE(ctx->rings->cq_overflow, + atomic_inc_return(&ctx->cached_cq_overflow)); } } @@ -733,6 +737,14 @@ static unsigned io_cqring_events(struct io_rings *rings) return READ_ONCE(rings->cq.tail) - READ_ONCE(rings->cq.head); } +static inline unsigned int io_sqring_entries(struct io_ring_ctx *ctx) +{ + struct io_rings *rings = ctx->rings; + + /* make sure SQ entry isn't read before tail */ + return smp_load_acquire(&rings->sq.tail) - ctx->cached_sq_head; +} + /* * Find and free completed poll iocbs */ @@ -862,19 +874,11 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx) mutex_unlock(&ctx->uring_lock); } -static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, - long min) +static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, + long min) { - int iters, ret = 0; + int iters = 0, ret = 0; - /* - * We disallow the app entering submit/complete with polling, but we - * still need to lock the ring to prevent racing with polled issue - * that got punted to a workqueue. - */ - mutex_lock(&ctx->uring_lock); - - iters = 0; do { int tmin = 0; @@ -910,30 +914,45 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, ret = 0; } while (min && !*nr_events && !need_resched()); + return ret; +} + +static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, + long min) +{ + int ret; + + /* + * We disallow the app entering submit/complete with polling, but we + * still need to lock the ring to prevent racing with polled issue + * that got punted to a workqueue. + */ + mutex_lock(&ctx->uring_lock); + ret = __io_iopoll_check(ctx, nr_events, min); mutex_unlock(&ctx->uring_lock); return ret; } -static void kiocb_end_write(struct kiocb *kiocb) +static void kiocb_end_write(struct io_kiocb *req) { - if (kiocb->ki_flags & IOCB_WRITE) { - struct inode *inode = file_inode(kiocb->ki_filp); + /* + * Tell lockdep we inherited freeze protection from submission + * thread. + */ + if (req->flags & REQ_F_ISREG) { + struct inode *inode = file_inode(req->file); - /* - * Tell lockdep we inherited freeze protection from submission - * thread. - */ - if (S_ISREG(inode->i_mode)) - __sb_writers_acquired(inode->i_sb, SB_FREEZE_WRITE); - file_end_write(kiocb->ki_filp); + __sb_writers_acquired(inode->i_sb, SB_FREEZE_WRITE); } + file_end_write(req->file); } static void io_complete_rw(struct kiocb *kiocb, long res, long res2) { struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw); - kiocb_end_write(kiocb); + if (kiocb->ki_flags & IOCB_WRITE) + kiocb_end_write(req); if ((req->flags & REQ_F_LINK) && res != req->result) req->flags |= REQ_F_FAIL_LINK; @@ -945,7 +964,8 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res, long res2) { struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw); - kiocb_end_write(kiocb); + if (kiocb->ki_flags & IOCB_WRITE) + kiocb_end_write(req); if ((req->flags & REQ_F_LINK) && res != req->result) req->flags |= REQ_F_FAIL_LINK; @@ -1059,8 +1079,17 @@ static int io_prep_rw(struct io_kiocb *req, const struct sqe_submit *s, if (!req->file) return -EBADF; - if (force_nonblock && !io_file_supports_async(req->file)) - force_nonblock = false; + if (S_ISREG(file_inode(req->file)->i_mode)) + req->flags |= REQ_F_ISREG; + + /* + * If the file doesn't support async, mark it as REQ_F_MUST_PUNT so + * we know to async punt it even if it was opened O_NONBLOCK + */ + if (force_nonblock && !io_file_supports_async(req->file)) { + req->flags |= REQ_F_MUST_PUNT; + return -EAGAIN; + } kiocb->ki_pos = READ_ONCE(sqe->off); kiocb->ki_flags = iocb_flags(kiocb->ki_filp); @@ -1081,7 +1110,8 @@ static int io_prep_rw(struct io_kiocb *req, const struct sqe_submit *s, return ret; /* don't allow async punt if RWF_NOWAIT was requested */ - if (kiocb->ki_flags & IOCB_NOWAIT) + if ((kiocb->ki_flags & IOCB_NOWAIT) || + (req->file->f_flags & O_NONBLOCK)) req->flags |= REQ_F_NOWAIT; if (force_nonblock) @@ -1094,6 +1124,7 @@ static int io_prep_rw(struct io_kiocb *req, const struct sqe_submit *s, kiocb->ki_flags |= IOCB_HIPRI; kiocb->ki_complete = io_complete_rw_iopoll; + req->result = 0; } else { if (kiocb->ki_flags & IOCB_HIPRI) return -EINVAL; @@ -1382,7 +1413,9 @@ static int io_read(struct io_kiocb *req, const struct sqe_submit *s, * need async punt anyway, so it's more efficient to do it * here. */ - if (force_nonblock && ret2 > 0 && ret2 < read_size) + if (force_nonblock && !(req->flags & REQ_F_NOWAIT) && + (req->flags & REQ_F_ISREG) && + ret2 > 0 && ret2 < read_size) ret2 = -EAGAIN; /* Catch -EAGAIN return for forced non-blocking submission */ if (!force_nonblock || ret2 != -EAGAIN) { @@ -1447,7 +1480,7 @@ static int io_write(struct io_kiocb *req, const struct sqe_submit *s, * released so that it doesn't complain about the held lock when * we return to userspace. */ - if (S_ISREG(file_inode(file)->i_mode)) { + if (req->flags & REQ_F_ISREG) { __sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true); __sb_writers_release(file_inode(file)->i_sb, @@ -1862,7 +1895,7 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe) static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer) { struct io_ring_ctx *ctx; - struct io_kiocb *req; + struct io_kiocb *req, *prev; unsigned long flags; req = container_of(timer, struct io_kiocb, timeout.timer); @@ -1870,6 +1903,15 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer) atomic_inc(&ctx->cq_timeouts); spin_lock_irqsave(&ctx->completion_lock, flags); + /* + * Adjust the reqs sequence before the current one because it + * will consume a slot in the cq_ring and the the cq_tail pointer + * will be increased, otherwise other timeout reqs may return in + * advance without waiting for enough wait_nr. + */ + prev = req; + list_for_each_entry_continue_reverse(prev, &ctx->timeout_list, list) + prev->sequence++; list_del(&req->list); io_cqring_fill_event(ctx, req->user_data, -ETIME); @@ -1884,10 +1926,11 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer) static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe) { - unsigned count, req_dist, tail_index; + unsigned count; struct io_ring_ctx *ctx = req->ctx; struct list_head *entry; struct timespec64 ts; + unsigned span = 0; if (unlikely(ctx->flags & IORING_SETUP_IOPOLL)) return -EINVAL; @@ -1907,23 +1950,46 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe) count = 1; req->sequence = ctx->cached_sq_head + count - 1; + /* reuse it to store the count */ + req->submit.sequence = count; req->flags |= REQ_F_TIMEOUT; /* * Insertion sort, ensuring the first entry in the list is always * the one we need first. */ - tail_index = ctx->cached_cq_tail - ctx->rings->sq_dropped; - req_dist = req->sequence - tail_index; spin_lock_irq(&ctx->completion_lock); list_for_each_prev(entry, &ctx->timeout_list) { struct io_kiocb *nxt = list_entry(entry, struct io_kiocb, list); - unsigned dist; + unsigned nxt_sq_head; + long long tmp, tmp_nxt; + + /* + * Since cached_sq_head + count - 1 can overflow, use type long + * long to store it. + */ + tmp = (long long)ctx->cached_sq_head + count - 1; + nxt_sq_head = nxt->sequence - nxt->submit.sequence + 1; + tmp_nxt = (long long)nxt_sq_head + nxt->submit.sequence - 1; - dist = nxt->sequence - tail_index; - if (req_dist >= dist) + /* + * cached_sq_head may overflow, and it will never overflow twice + * once there is some timeout req still be valid. + */ + if (ctx->cached_sq_head < nxt_sq_head) + tmp += UINT_MAX; + + if (tmp > tmp_nxt) break; + + /* + * Sequence of reqs after the insert one and itself should + * be adjusted because each timeout req consumes a slot. + */ + span++; + nxt->sequence++; } + req->sequence -= span; list_add(&req->list, entry); spin_unlock_irq(&ctx->completion_lock); @@ -2262,12 +2328,18 @@ static int io_req_set_file(struct io_ring_ctx *ctx, const struct sqe_submit *s, } static int __io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req, - struct sqe_submit *s, bool force_nonblock) + struct sqe_submit *s) { int ret; - ret = __io_submit_sqe(ctx, req, s, force_nonblock); - if (ret == -EAGAIN && !(req->flags & REQ_F_NOWAIT)) { + ret = __io_submit_sqe(ctx, req, s, true); + + /* + * We async punt it if the file wasn't marked NOWAIT, or if the file + * doesn't support non-blocking read/write attempts + */ + if (ret == -EAGAIN && (!(req->flags & REQ_F_NOWAIT) || + (req->flags & REQ_F_MUST_PUNT))) { struct io_uring_sqe *sqe_copy; sqe_copy = kmemdup(s->sqe, sizeof(*sqe_copy), GFP_KERNEL); @@ -2307,7 +2379,7 @@ static int __io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req, } static int io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req, - struct sqe_submit *s, bool force_nonblock) + struct sqe_submit *s) { int ret; @@ -2320,18 +2392,17 @@ static int io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req, return 0; } - return __io_queue_sqe(ctx, req, s, force_nonblock); + return __io_queue_sqe(ctx, req, s); } static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req, - struct sqe_submit *s, struct io_kiocb *shadow, - bool force_nonblock) + struct sqe_submit *s, struct io_kiocb *shadow) { int ret; int need_submit = false; if (!shadow) - return io_queue_sqe(ctx, req, s, force_nonblock); + return io_queue_sqe(ctx, req, s); /* * Mark the first IO in link list as DRAIN, let all the following @@ -2343,6 +2414,7 @@ static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req, if (ret) { if (ret != -EIOCBQUEUED) { io_free_req(req); + __io_free_req(shadow); io_cqring_add_event(ctx, s->sqe->user_data, ret); return 0; } @@ -2360,7 +2432,7 @@ static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req, spin_unlock_irq(&ctx->completion_lock); if (need_submit) - return __io_queue_sqe(ctx, req, s, force_nonblock); + return __io_queue_sqe(ctx, req, s); return 0; } @@ -2368,8 +2440,7 @@ static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req, #define SQE_VALID_FLAGS (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK) static void io_submit_sqe(struct io_ring_ctx *ctx, struct sqe_submit *s, - struct io_submit_state *state, struct io_kiocb **link, - bool force_nonblock) + struct io_submit_state *state, struct io_kiocb **link) { struct io_uring_sqe *sqe_copy; struct io_kiocb *req; @@ -2396,6 +2467,8 @@ static void io_submit_sqe(struct io_ring_ctx *ctx, struct sqe_submit *s, return; } + req->user_data = s->sqe->user_data; + /* * If we already have a head request, queue this one for async * submittal once the head completes. If we don't have a head but @@ -2422,7 +2495,7 @@ static void io_submit_sqe(struct io_ring_ctx *ctx, struct sqe_submit *s, INIT_LIST_HEAD(&req->link_list); *link = req; } else { - io_queue_sqe(ctx, req, s, force_nonblock); + io_queue_sqe(ctx, req, s); } } @@ -2502,12 +2575,13 @@ static bool io_get_sqring(struct io_ring_ctx *ctx, struct sqe_submit *s) /* drop invalid entries */ ctx->cached_sq_head++; - rings->sq_dropped++; + ctx->cached_sq_dropped++; + WRITE_ONCE(rings->sq_dropped, ctx->cached_sq_dropped); return false; } -static int io_submit_sqes(struct io_ring_ctx *ctx, struct sqe_submit *sqes, - unsigned int nr, bool has_user, bool mm_fault) +static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr, + bool has_user, bool mm_fault) { struct io_submit_state state, *statep = NULL; struct io_kiocb *link = NULL; @@ -2521,19 +2595,23 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, struct sqe_submit *sqes, } for (i = 0; i < nr; i++) { + struct sqe_submit s; + + if (!io_get_sqring(ctx, &s)) + break; + /* * If previous wasn't linked and we have a linked command, * that's the end of the chain. Submit the previous link. */ if (!prev_was_link && link) { - io_queue_link_head(ctx, link, &link->submit, shadow_req, - true); + io_queue_link_head(ctx, link, &link->submit, shadow_req); link = NULL; shadow_req = NULL; } - prev_was_link = (sqes[i].sqe->flags & IOSQE_IO_LINK) != 0; + prev_was_link = (s.sqe->flags & IOSQE_IO_LINK) != 0; - if (link && (sqes[i].sqe->flags & IOSQE_IO_DRAIN)) { + if (link && (s.sqe->flags & IOSQE_IO_DRAIN)) { if (!shadow_req) { shadow_req = io_get_req(ctx, NULL); if (unlikely(!shadow_req)) @@ -2541,24 +2619,24 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, struct sqe_submit *sqes, shadow_req->flags |= (REQ_F_IO_DRAIN | REQ_F_SHADOW_DRAIN); refcount_dec(&shadow_req->refs); } - shadow_req->sequence = sqes[i].sequence; + shadow_req->sequence = s.sequence; } out: if (unlikely(mm_fault)) { - io_cqring_add_event(ctx, sqes[i].sqe->user_data, + io_cqring_add_event(ctx, s.sqe->user_data, -EFAULT); } else { - sqes[i].has_user = has_user; - sqes[i].needs_lock = true; - sqes[i].needs_fixed_file = true; - io_submit_sqe(ctx, &sqes[i], statep, &link, true); + s.has_user = has_user; + s.needs_lock = true; + s.needs_fixed_file = true; + io_submit_sqe(ctx, &s, statep, &link); submitted++; } } if (link) - io_queue_link_head(ctx, link, &link->submit, shadow_req, true); + io_queue_link_head(ctx, link, &link->submit, shadow_req); if (statep) io_submit_state_end(&state); @@ -2567,7 +2645,6 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, struct sqe_submit *sqes, static int io_sq_thread(void *data) { - struct sqe_submit sqes[IO_IOPOLL_BATCH]; struct io_ring_ctx *ctx = data; struct mm_struct *cur_mm = NULL; mm_segment_t old_fs; @@ -2582,14 +2659,27 @@ static int io_sq_thread(void *data) timeout = inflight = 0; while (!kthread_should_park()) { - bool all_fixed, mm_fault = false; - int i; + bool mm_fault = false; + unsigned int to_submit; if (inflight) { unsigned nr_events = 0; if (ctx->flags & IORING_SETUP_IOPOLL) { - io_iopoll_check(ctx, &nr_events, 0); + /* + * inflight is the count of the maximum possible + * entries we submitted, but it can be smaller + * if we dropped some of them. If we don't have + * poll entries available, then we know that we + * have nothing left to poll for. Reset the + * inflight count to zero in that case. + */ + mutex_lock(&ctx->uring_lock); + if (!list_empty(&ctx->poll_list)) + __io_iopoll_check(ctx, &nr_events, 0); + else + inflight = 0; + mutex_unlock(&ctx->uring_lock); } else { /* * Normal IO, just pretend everything completed. @@ -2603,7 +2693,8 @@ static int io_sq_thread(void *data) timeout = jiffies + ctx->sq_thread_idle; } - if (!io_get_sqring(ctx, &sqes[0])) { + to_submit = io_sqring_entries(ctx); + if (!to_submit) { /* * We're polling. If we're within the defined idle * period, then let us spin without work before going @@ -2634,7 +2725,8 @@ static int io_sq_thread(void *data) /* make sure to read SQ tail after writing flags */ smp_mb(); - if (!io_get_sqring(ctx, &sqes[0])) { + to_submit = io_sqring_entries(ctx); + if (!to_submit) { if (kthread_should_park()) { finish_wait(&ctx->sqo_wait, &wait); break; @@ -2652,19 +2744,8 @@ static int io_sq_thread(void *data) ctx->rings->sq_flags &= ~IORING_SQ_NEED_WAKEUP; } - i = 0; - all_fixed = true; - do { - if (all_fixed && io_sqe_needs_user(sqes[i].sqe)) - all_fixed = false; - - i++; - if (i == ARRAY_SIZE(sqes)) - break; - } while (io_get_sqring(ctx, &sqes[i])); - /* Unless all new commands are FIXED regions, grab mm */ - if (!all_fixed && !cur_mm) { + if (!cur_mm) { mm_fault = !mmget_not_zero(ctx->sqo_mm); if (!mm_fault) { use_mm(ctx->sqo_mm); @@ -2672,8 +2753,9 @@ static int io_sq_thread(void *data) } } - inflight += io_submit_sqes(ctx, sqes, i, cur_mm != NULL, - mm_fault); + to_submit = min(to_submit, ctx->sq_entries); + inflight += io_submit_sqes(ctx, to_submit, cur_mm != NULL, + mm_fault); /* Commit SQ ring head once we've consumed all SQEs */ io_commit_sqring(ctx); @@ -2690,8 +2772,7 @@ static int io_sq_thread(void *data) return 0; } -static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit, - bool block_for_last) +static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit) { struct io_submit_state state, *statep = NULL; struct io_kiocb *link = NULL; @@ -2705,7 +2786,6 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit, } for (i = 0; i < to_submit; i++) { - bool force_nonblock = true; struct sqe_submit s; if (!io_get_sqring(ctx, &s)) @@ -2716,8 +2796,7 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit, * that's the end of the chain. Submit the previous link. */ if (!prev_was_link && link) { - io_queue_link_head(ctx, link, &link->submit, shadow_req, - force_nonblock); + io_queue_link_head(ctx, link, &link->submit, shadow_req); link = NULL; shadow_req = NULL; } @@ -2739,27 +2818,16 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit, s.needs_lock = false; s.needs_fixed_file = false; submit++; - - /* - * The caller will block for events after submit, submit the - * last IO non-blocking. This is either the only IO it's - * submitting, or it already submitted the previous ones. This - * improves performance by avoiding an async punt that we don't - * need to do. - */ - if (block_for_last && submit == to_submit) - force_nonblock = false; - - io_submit_sqe(ctx, &s, statep, &link, force_nonblock); + io_submit_sqe(ctx, &s, statep, &link); } - io_commit_sqring(ctx); if (link) - io_queue_link_head(ctx, link, &link->submit, shadow_req, - !block_for_last); + io_queue_link_head(ctx, link, &link->submit, shadow_req); if (statep) io_submit_state_end(statep); + io_commit_sqring(ctx); + return submit; } @@ -3600,21 +3668,10 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit, wake_up(&ctx->sqo_wait); submitted = to_submit; } else if (to_submit) { - bool block_for_last = false; - to_submit = min(to_submit, ctx->sq_entries); - /* - * Allow last submission to block in a series, IFF the caller - * asked to wait for events and we don't currently have - * enough. This potentially avoids an async punt. - */ - if (to_submit == min_complete && - io_cqring_events(ctx->rings) < min_complete) - block_for_last = true; - mutex_lock(&ctx->uring_lock); - submitted = io_ring_submit(ctx, to_submit, block_for_last); + submitted = io_ring_submit(ctx, to_submit); mutex_unlock(&ctx->uring_lock); } if (flags & IORING_ENTER_GETEVENTS) { @@ -3773,10 +3830,6 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p) if (ret) goto err; - ret = io_uring_get_fd(ctx); - if (ret < 0) - goto err; - memset(&p->sq_off, 0, sizeof(p->sq_off)); p->sq_off.head = offsetof(struct io_rings, sq.head); p->sq_off.tail = offsetof(struct io_rings, sq.tail); @@ -3794,6 +3847,14 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p) p->cq_off.overflow = offsetof(struct io_rings, cq_overflow); p->cq_off.cqes = offsetof(struct io_rings, cqes); + /* + * Install ring fd as the very last thing, so we don't risk someone + * having closed it before we finish setup + */ + ret = io_uring_get_fd(ctx); + if (ret < 0) + goto err; + p->features = IORING_FEAT_SINGLE_MMAP; return ret; err: diff --git a/fs/libfs.c b/fs/libfs.c index 540611b99b9aa07cae8693e8de46e9fd78e518d6..1463b038ffc4e6f34dd5e213820df57a67106640 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -473,8 +473,7 @@ EXPORT_SYMBOL(simple_write_begin); /** * simple_write_end - .write_end helper for non-block-device FSes - * @available: See .write_end of address_space_operations - * @file: " + * @file: See .write_end of address_space_operations * @mapping: " * @pos: " * @len: " diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 071b90a45933a4b95c176e8042a29130e07a71f1..af549d70ec507e3f8deb920c3a93509bd59a5ed2 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -53,6 +53,16 @@ nfs4_is_valid_delegation(const struct nfs_delegation *delegation, return false; } +struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode) +{ + struct nfs_delegation *delegation; + + delegation = rcu_dereference(NFS_I(inode)->delegation); + if (nfs4_is_valid_delegation(delegation, 0)) + return delegation; + return NULL; +} + static int nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark) { @@ -1181,7 +1191,7 @@ bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode) if (delegation != NULL && nfs4_stateid_match_other(dst, &delegation->stateid)) { dst->seqid = delegation->stateid.seqid; - return ret; + ret = true; } rcu_read_unlock(); out: diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 9eb87ae4c98276632ab799e5b66487df9cdcd3e4..8b14d441e699bc472a4a4c60c5e969384aca0233 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -68,6 +68,7 @@ int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred); bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode); +struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode); void nfs_mark_delegation_referenced(struct nfs_delegation *delegation); int nfs4_have_delegation(struct inode *inode, fmode_t flags); int nfs4_check_delegation(struct inode *inode, fmode_t flags); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ab8ca20fd5790a9e0d129b3a4d7f3a397a1dd9e2..caacf5e7f5e1568474feb57f6e4d85aa19efdc8b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1440,8 +1440,6 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode, return 0; if ((delegation->type & fmode) != fmode) return 0; - if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) - return 0; switch (claim) { case NFS4_OPEN_CLAIM_NULL: case NFS4_OPEN_CLAIM_FH: @@ -1810,7 +1808,6 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) { struct nfs4_state *state = opendata->state; - struct nfs_inode *nfsi = NFS_I(state->inode); struct nfs_delegation *delegation; int open_mode = opendata->o_arg.open_flags; fmode_t fmode = opendata->o_arg.fmode; @@ -1827,7 +1824,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) } spin_unlock(&state->owner->so_lock); rcu_read_lock(); - delegation = rcu_dereference(nfsi->delegation); + delegation = nfs4_get_valid_delegation(state->inode); if (!can_open_delegated(delegation, fmode, claim)) { rcu_read_unlock(); break; @@ -2371,7 +2368,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) data->o_arg.open_flags, claim)) goto out_no_action; rcu_read_lock(); - delegation = rcu_dereference(NFS_I(data->state->inode)->delegation); + delegation = nfs4_get_valid_delegation(data->state->inode); if (can_open_delegated(delegation, data->o_arg.fmode, claim)) goto unlock_no_action; rcu_read_unlock(); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 2e982db3e1ae4b55eb8bc741b9ca9400c791afad..53939bf9d7d260f1ebfb1da514973a76a92322b3 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1230,6 +1230,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid)); if (IS_ERR(transfer_to[USRQUOTA])) { status = PTR_ERR(transfer_to[USRQUOTA]); + transfer_to[USRQUOTA] = NULL; goto bail_unlock; } } @@ -1239,6 +1240,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid)); if (IS_ERR(transfer_to[GRPQUOTA])) { status = PTR_ERR(transfer_to[GRPQUOTA]); + transfer_to[GRPQUOTA] = NULL; goto bail_unlock; } } diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 930e3d388579138cc22016ede4393311ea8e54a3..699a560efbb02b498b01ba2df49f5b334766fa59 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -217,7 +217,8 @@ void ocfs2_recovery_exit(struct ocfs2_super *osb) /* At this point, we know that no more recovery threads can be * launched, so wait for any recovery completion work to * complete. */ - flush_workqueue(osb->ocfs2_wq); + if (osb->ocfs2_wq) + flush_workqueue(osb->ocfs2_wq); /* * Now that recovery is shut down, and the osb is about to be diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 158e5af767fd11119b39947586cdb364f4c6a6d2..720e9f94957e39047d434bfb3c1a2549a50056fc 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -377,7 +377,8 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) struct ocfs2_dinode *alloc = NULL; cancel_delayed_work(&osb->la_enable_wq); - flush_workqueue(osb->ocfs2_wq); + if (osb->ocfs2_wq) + flush_workqueue(osb->ocfs2_wq); if (osb->local_alloc_state == OCFS2_LA_UNUSED) goto out; diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index ac9247371871d9069687519b0cb06a21f30330e5..8c1f1bb1a5ce3fd1d9e757a87805fb3df638206c 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -132,9 +132,9 @@ static int meminfo_proc_show(struct seq_file *m, void *v) global_node_page_state(NR_SHMEM_THPS) * HPAGE_PMD_NR); show_val_kb(m, "ShmemPmdMapped: ", global_node_page_state(NR_SHMEM_PMDMAPPED) * HPAGE_PMD_NR); - show_val_kb(m, "FileHugePages: ", + show_val_kb(m, "FileHugePages: ", global_node_page_state(NR_FILE_THPS) * HPAGE_PMD_NR); - show_val_kb(m, "FilePmdMapped: ", + show_val_kb(m, "FilePmdMapped: ", global_node_page_state(NR_FILE_PMDMAPPED) * HPAGE_PMD_NR); #endif diff --git a/fs/proc/page.c b/fs/proc/page.c index 544d1ee15aeece96efa3e5b39a9481c879584419..7c952ee732e63dffd0ae09f92a6ec3e6c57e5771 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c @@ -42,10 +42,12 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf, return -EINVAL; while (count > 0) { - if (pfn_valid(pfn)) - ppage = pfn_to_page(pfn); - else - ppage = NULL; + /* + * TODO: ZONE_DEVICE support requires to identify + * memmaps that were actually initialized. + */ + ppage = pfn_to_online_page(pfn); + if (!ppage || PageSlab(ppage) || page_has_type(ppage)) pcount = 0; else @@ -216,10 +218,11 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf, return -EINVAL; while (count > 0) { - if (pfn_valid(pfn)) - ppage = pfn_to_page(pfn); - else - ppage = NULL; + /* + * TODO: ZONE_DEVICE support requires to identify + * memmaps that were actually initialized. + */ + ppage = pfn_to_online_page(pfn); if (put_user(stable_page_flags(ppage), out)) { ret = -EFAULT; @@ -261,10 +264,11 @@ static ssize_t kpagecgroup_read(struct file *file, char __user *buf, return -EINVAL; while (count > 0) { - if (pfn_valid(pfn)) - ppage = pfn_to_page(pfn); - else - ppage = NULL; + /* + * TODO: ZONE_DEVICE support requires to identify + * memmaps that were actually initialized. + */ + ppage = pfn_to_online_page(pfn); if (ppage) ino = page_cgroup_ino(ppage); diff --git a/fs/readdir.c b/fs/readdir.c index 6e2623e57b2e81ce3292016caeea82695d783d36..d26d5ea4de7b8958ea3d48069cd873b50398cd88 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -105,9 +105,9 @@ EXPORT_SYMBOL(iterate_dir); */ static int verify_dirent_name(const char *name, int len) { - if (WARN_ON_ONCE(!len)) + if (!len) return -EIO; - if (WARN_ON_ONCE(memchr(name, '/', len))) + if (memchr(name, '/', len)) return -EIO; return 0; } diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 818122410bfe3e579c14eb3ee5a7c7159be5c808..19fa9c4af46266af5933fe448718d4a0ca160202 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -21,6 +21,7 @@ #include "sdcardfs.h" #include #include +#include #include #include #include @@ -293,6 +294,9 @@ static int __sdcardfs_fill_super( list_add(&sb_info->list, &sdcardfs_super_list); mutex_unlock(&sdcardfs_super_list_lock); + sb_info->fscrypt_nb.notifier_call = sdcardfs_on_fscrypt_key_removed; + fscrypt_register_key_removal_notifier(&sb_info->fscrypt_nb); + if (!(fc->sb_flags & SB_SILENT)) pr_info("sdcardfs: mounted on top of %s type %s\n", dev_name, lower_sb->s_type->name); @@ -331,6 +335,9 @@ void sdcardfs_kill_sb(struct super_block *sb) if (sb->s_magic == SDCARDFS_SUPER_MAGIC && sb->s_fs_info) { sbi = SDCARDFS_SB(sb); + + fscrypt_unregister_key_removal_notifier(&sbi->fscrypt_nb); + mutex_lock(&sdcardfs_super_list_lock); list_del(&sbi->list); mutex_unlock(&sdcardfs_super_list_lock); diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index f813d23cddcdcac5d960f3f23b345afcf2d2b598..4af4f163399b184a20912bdd5f9aee2f40ec3a80 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -152,6 +152,8 @@ extern struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id); extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, struct path *lower_path, userid_t id); +extern int sdcardfs_on_fscrypt_key_removed(struct notifier_block *nb, + unsigned long action, void *data); /* file private data */ struct sdcardfs_file_info { @@ -231,6 +233,7 @@ struct sdcardfs_sb_info { struct path obbpath; void *pkgl_id; struct list_head list; + struct notifier_block fscrypt_nb; }; /* diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c index 6b1d27e5067b4ed743063ed990bb7f573ce9a9a1..3d8762e012b81b749e8b7cccf8e02e529effc6f5 100644 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -282,6 +282,23 @@ static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m, return 0; }; +int sdcardfs_on_fscrypt_key_removed(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct sdcardfs_sb_info *sbi = container_of(nb, struct sdcardfs_sb_info, + fscrypt_nb); + + /* + * Evict any unused sdcardfs dentries (and hence any unused sdcardfs + * inodes, since sdcardfs doesn't cache unpinned inodes by themselves) + * so that the lower filesystem's encrypted inodes can be evicted. + * This is needed to make the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl + * properly "lock" the files underneath the sdcardfs mount. + */ + shrink_dcache_sb(sbi->sb); + return NOTIFY_OK; +} + const struct super_operations sdcardfs_sops = { .put_super = sdcardfs_put_super, .statfs = sdcardfs_statfs, diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 39dd2b90810626b5075e9c5242532390c53f0148..e9371a8e0e26ffd30f8e2892e549c9357eb0fedd 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -366,11 +366,11 @@ struct xfs_bulkstat { uint64_t bs_blocks; /* number of blocks */ uint64_t bs_xflags; /* extended flags */ - uint64_t bs_atime; /* access time, seconds */ - uint64_t bs_mtime; /* modify time, seconds */ + int64_t bs_atime; /* access time, seconds */ + int64_t bs_mtime; /* modify time, seconds */ - uint64_t bs_ctime; /* inode change time, seconds */ - uint64_t bs_btime; /* creation time, seconds */ + int64_t bs_ctime; /* inode change time, seconds */ + int64_t bs_btime; /* creation time, seconds */ uint32_t bs_gen; /* generation count */ uint32_t bs_uid; /* user id */ diff --git a/include/acpi/processor.h b/include/acpi/processor.h index f936033cb9e6d57e0b965b5cb742ac868c10c463..47805172e73d80e4ee3c771a462b0c1840847a10 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -232,8 +232,8 @@ struct acpi_processor { struct acpi_processor_limit limit; struct thermal_cooling_device *cdev; struct device *dev; /* Processor device. */ - struct dev_pm_qos_request perflib_req; - struct dev_pm_qos_request thermal_req; + struct freq_qos_request perflib_req; + struct freq_qos_request thermal_req; }; struct acpi_processor_errata { @@ -302,8 +302,8 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx #ifdef CONFIG_CPU_FREQ extern bool acpi_processor_cpufreq_init; void acpi_processor_ignore_ppc_init(void); -void acpi_processor_ppc_init(int cpu); -void acpi_processor_ppc_exit(int cpu); +void acpi_processor_ppc_init(struct cpufreq_policy *policy); +void acpi_processor_ppc_exit(struct cpufreq_policy *policy); void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag); extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit); #else @@ -311,11 +311,11 @@ static inline void acpi_processor_ignore_ppc_init(void) { return; } -static inline void acpi_processor_ppc_init(int cpu) +static inline void acpi_processor_ppc_init(struct cpufreq_policy *policy) { return; } -static inline void acpi_processor_ppc_exit(int cpu) +static inline void acpi_processor_ppc_exit(struct cpufreq_policy *policy) { return; } @@ -431,14 +431,14 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr) int acpi_processor_get_limit_info(struct acpi_processor *pr); extern const struct thermal_cooling_device_ops processor_cooling_ops; #if defined(CONFIG_ACPI_CPU_FREQ_PSS) & defined(CONFIG_CPU_FREQ) -void acpi_thermal_cpufreq_init(int cpu); -void acpi_thermal_cpufreq_exit(int cpu); +void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy); +void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy); #else -static inline void acpi_thermal_cpufreq_init(int cpu) +static inline void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy) { return; } -static inline void acpi_thermal_cpufreq_exit(int cpu) +static inline void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy) { return; } diff --git a/include/linux/bio-crypt-ctx.h b/include/linux/bio-crypt-ctx.h new file mode 100644 index 0000000000000000000000000000000000000000..7c389f310bab9c1bc28b82d55971f694bb2a782d --- /dev/null +++ b/include/linux/bio-crypt-ctx.h @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + */ +#ifndef __LINUX_BIO_CRYPT_CTX_H +#define __LINUX_BIO_CRYPT_CTX_H + +enum blk_crypto_mode_num { + BLK_ENCRYPTION_MODE_INVALID = 0, + BLK_ENCRYPTION_MODE_AES_256_XTS = 1, +}; + +#ifdef CONFIG_BLOCK +#include + +#ifdef CONFIG_BLK_INLINE_ENCRYPTION +struct bio_crypt_ctx { + int keyslot; + const u8 *raw_key; + enum blk_crypto_mode_num crypto_mode; + u64 data_unit_num; + unsigned int data_unit_size_bits; + + /* + * The keyslot manager where the key has been programmed + * with keyslot. + */ + struct keyslot_manager *processing_ksm; + + /* + * Copy of the bvec_iter when this bio was submitted. + * We only want to en/decrypt the part of the bio + * as described by the bvec_iter upon submission because + * bio might be split before being resubmitted + */ + struct bvec_iter crypt_iter; + u64 sw_data_unit_num; +}; + +extern int bio_crypt_clone(struct bio *dst, struct bio *src, + gfp_t gfp_mask); + +static inline bool bio_has_crypt_ctx(struct bio *bio) +{ + return bio->bi_crypt_context; +} + +static inline void bio_crypt_advance(struct bio *bio, unsigned int bytes) +{ + if (bio_has_crypt_ctx(bio)) { + bio->bi_crypt_context->data_unit_num += + bytes >> bio->bi_crypt_context->data_unit_size_bits; + } +} + +extern bool bio_crypt_swhandled(struct bio *bio); + +static inline bool bio_crypt_has_keyslot(struct bio *bio) +{ + return bio->bi_crypt_context->keyslot >= 0; +} + +extern int bio_crypt_ctx_init(void); + +extern struct bio_crypt_ctx *bio_crypt_alloc_ctx(gfp_t gfp_mask); + +extern void bio_crypt_free_ctx(struct bio *bio); + +static inline int bio_crypt_set_ctx(struct bio *bio, + const u8 *raw_key, + enum blk_crypto_mode_num crypto_mode, + u64 dun, + unsigned int dun_bits, + gfp_t gfp_mask) +{ + struct bio_crypt_ctx *crypt_ctx; + + crypt_ctx = bio_crypt_alloc_ctx(gfp_mask); + if (!crypt_ctx) + return -ENOMEM; + + crypt_ctx->raw_key = raw_key; + crypt_ctx->data_unit_num = dun; + crypt_ctx->data_unit_size_bits = dun_bits; + crypt_ctx->crypto_mode = crypto_mode; + crypt_ctx->processing_ksm = NULL; + crypt_ctx->keyslot = -1; + bio->bi_crypt_context = crypt_ctx; + + return 0; +} + +static inline void bio_set_data_unit_num(struct bio *bio, u64 dun) +{ + bio->bi_crypt_context->data_unit_num = dun; +} + +static inline int bio_crypt_get_keyslot(struct bio *bio) +{ + return bio->bi_crypt_context->keyslot; +} + +static inline void bio_crypt_set_keyslot(struct bio *bio, + unsigned int keyslot, + struct keyslot_manager *ksm) +{ + bio->bi_crypt_context->keyslot = keyslot; + bio->bi_crypt_context->processing_ksm = ksm; +} + +extern void bio_crypt_ctx_release_keyslot(struct bio *bio); + +extern int bio_crypt_ctx_acquire_keyslot(struct bio *bio, + struct keyslot_manager *ksm); + +static inline const u8 *bio_crypt_raw_key(struct bio *bio) +{ + return bio->bi_crypt_context->raw_key; +} + +static inline enum blk_crypto_mode_num bio_crypto_mode(struct bio *bio) +{ + return bio->bi_crypt_context->crypto_mode; +} + +static inline u64 bio_crypt_data_unit_num(struct bio *bio) +{ + return bio->bi_crypt_context->data_unit_num; +} + +static inline u64 bio_crypt_sw_data_unit_num(struct bio *bio) +{ + return bio->bi_crypt_context->sw_data_unit_num; +} + +extern bool bio_crypt_should_process(struct bio *bio, struct request_queue *q); + +extern bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2); + +extern bool bio_crypt_ctx_back_mergeable(struct bio *b_1, + unsigned int b1_sectors, + struct bio *b_2); + +#else /* CONFIG_BLK_INLINE_ENCRYPTION */ +struct keyslot_manager; + +static inline int bio_crypt_ctx_init(void) +{ + return 0; +} + +static inline int bio_crypt_clone(struct bio *dst, struct bio *src, + gfp_t gfp_mask) +{ + return 0; +} + +static inline void bio_crypt_advance(struct bio *bio, + unsigned int bytes) { } + +static inline bool bio_has_crypt_ctx(struct bio *bio) +{ + return false; +} + +static inline void bio_crypt_free_ctx(struct bio *bio) { } + +static inline void bio_crypt_set_ctx(struct bio *bio, + u8 *raw_key, + enum blk_crypto_mode_num crypto_mode, + u64 dun, + unsigned int dun_bits, + gfp_t gfp_mask) { } + +static inline bool bio_crypt_swhandled(struct bio *bio) +{ + return false; +} + +static inline void bio_set_data_unit_num(struct bio *bio, u64 dun) { } + +static inline bool bio_crypt_has_keyslot(struct bio *bio) +{ + return false; +} + +static inline void bio_crypt_set_keyslot(struct bio *bio, + unsigned int keyslot, + struct keyslot_manager *ksm) { } + +static inline int bio_crypt_get_keyslot(struct bio *bio) +{ + return -1; +} + +static inline u8 *bio_crypt_raw_key(struct bio *bio) +{ + return NULL; +} + +static inline u64 bio_crypt_data_unit_num(struct bio *bio) +{ + return 0; +} + +static inline bool bio_crypt_should_process(struct bio *bio, + struct request_queue *q) +{ + return false; +} + +static inline bool bio_crypt_ctx_compatible(struct bio *b_1, struct bio *b_2) +{ + return true; +} + +static inline bool bio_crypt_ctx_back_mergeable(struct bio *b_1, + unsigned int b1_sectors, + struct bio *b_2) +{ + return true; +} + +#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ +#endif /* CONFIG_BLOCK */ +#endif /* __LINUX_BIO_CRYPT_CTX_H */ diff --git a/include/linux/bio.h b/include/linux/bio.h index 3cdb84cdc48843bd970f41f6221e1467fd8b86ff..63d0fee423fafced45010300a270b142ff3bf312 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef CONFIG_BLOCK /* struct bio, bio_vec and BIO_* flags are defined in blk_types.h */ diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 90528f12bdfa6a3a28ed1e00e5ab7e68b104535c..29fc933df3bf0eaf5dae01b458854d9cb410eef9 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -326,10 +326,11 @@ static inline int bitmap_equal(const unsigned long *src1, } /** - * bitmap_or_equal - Check whether the or of two bitnaps is equal to a third + * bitmap_or_equal - Check whether the or of two bitmaps is equal to a third * @src1: Pointer to bitmap 1 * @src2: Pointer to bitmap 2 will be or'ed with bitmap 1 * @src3: Pointer to bitmap 3. Compare to the result of *@src1 | *@src2 + * @nbits: number of bits in each of these bitmaps * * Returns: True if (*@src1 | *@src2) == *@src3, false otherwise */ diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h new file mode 100644 index 0000000000000000000000000000000000000000..2a07401244a6b5b6f66f6932d918879ebbcc3696 --- /dev/null +++ b/include/linux/blk-crypto.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + */ + +#ifndef __LINUX_BLK_CRYPTO_H +#define __LINUX_BLK_CRYPTO_H + +#include +#include + +#ifdef CONFIG_BLK_INLINE_ENCRYPTION + +int blk_crypto_init(void); + +int blk_crypto_submit_bio(struct bio **bio_ptr); + +bool blk_crypto_endio(struct bio *bio); + +int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, + unsigned int data_unit_size, + struct request_queue *q); + +int blk_crypto_evict_key(struct request_queue *q, const u8 *key, + enum blk_crypto_mode_num mode, + unsigned int data_unit_size); + +#else /* CONFIG_BLK_INLINE_ENCRYPTION */ + +static inline int blk_crypto_init(void) +{ + return 0; +} + +static inline int blk_crypto_submit_bio(struct bio **bio_ptr) +{ + return 0; +} + +static inline bool blk_crypto_endio(struct bio *bio) +{ + return true; +} + +static inline int +blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num, + unsigned int data_unit_size, + struct request_queue *q) +{ + return -EOPNOTSUPP; +} + +static inline int blk_crypto_evict_key(struct request_queue *q, const u8 *key, + enum blk_crypto_mode_num mode, + unsigned int data_unit_size) +{ + return 0; +} + +#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ + +#endif /* __LINUX_BLK_CRYPTO_H */ diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index d688b96d1d633186fdbadaeaff7484b4c173c54f..d3ee2dcb634d6ae7ad32f7b4bfe3bab5cbd5a31d 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -18,6 +18,7 @@ struct block_device; struct io_context; struct cgroup_subsys_state; typedef void (bio_end_io_t) (struct bio *); +struct bio_crypt_ctx; /* * Block error status values. See block/blk-core:blk_errors for the details. @@ -173,6 +174,11 @@ struct bio { u64 bi_iocost_cost; #endif #endif + +#ifdef CONFIG_BLK_INLINE_ENCRYPTION + struct bio_crypt_ctx *bi_crypt_context; +#endif + union { #if defined(CONFIG_BLK_DEV_INTEGRITY) struct bio_integrity_payload *bi_integrity; /* data integrity */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f3ea78b0c91cf78063bc11610bb189cb7fdbc3bf..244e81a8f5d22b4641ea58c70960d1ef7005c62a 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -43,6 +43,7 @@ struct pr_ops; struct rq_qos; struct blk_queue_stats; struct blk_stat_callback; +struct keyslot_manager; #define BLKDEV_MIN_RQ 4 #define BLKDEV_MAX_RQ 128 /* Default maximum */ @@ -481,6 +482,11 @@ struct request_queue { unsigned int dma_pad_mask; unsigned int dma_alignment; +#ifdef CONFIG_BLK_INLINE_ENCRYPTION + /* Inline crypto capabilities */ + struct keyslot_manager *ksm; +#endif + unsigned int rq_timeout; int poll_nsec; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index fca45a2749d4c27e03d37a0fef8875da00310699..654812caafcd7c3bebc34b0561b5998c13a61375 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -76,8 +77,10 @@ struct cpufreq_policy { struct work_struct update; /* if update_policy() needs to be * called, but you're in IRQ context */ - struct dev_pm_qos_request *min_freq_req; - struct dev_pm_qos_request *max_freq_req; + struct freq_constraints constraints; + struct freq_qos_request *min_freq_req; + struct freq_qos_request *max_freq_req; + struct cpufreq_frequency_table *freq_table; enum cpufreq_table_sorting freq_table_sorted; diff --git a/include/linux/device.h b/include/linux/device.h index 6978bb471567a62c82168e66401ef163a050d953..d1bcc8f122f69b4b449af58676236c2442808646 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1096,6 +1096,7 @@ enum device_link_state { * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind. * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds. * MANAGED: The core tracks presence of supplier/consumer drivers (internal). + * SYNC_STATE_ONLY: Link only affects sync_state() behavior. */ #define DL_FLAG_STATELESS BIT(0) #define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1) @@ -1104,6 +1105,7 @@ enum device_link_state { #define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4) #define DL_FLAG_AUTOPROBE_CONSUMER BIT(5) #define DL_FLAG_MANAGED BIT(6) +#define DL_FLAG_SYNC_STATE_ONLY BIT(7) /** * struct device_link - Device link representation. @@ -1153,6 +1155,8 @@ enum dl_dev_state { * @consumers: List of links to consumer devices. * @needs_suppliers: Hook to global list of devices waiting for suppliers. * @defer_sync: Hook to global list of devices that have deferred sync_state. + * @need_for_probe: If needs_suppliers is on a list, this indicates if the + * suppliers are needed for probe or not. * @status: Driver status information. */ struct dev_links_info { @@ -1160,6 +1164,7 @@ struct dev_links_info { struct list_head consumers; struct list_head needs_suppliers; struct list_head defer_sync; + bool need_for_probe; enum dl_dev_state status; }; diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 6c809440f31978228acb3f29762ccb6901fd8341..4cf02ecd67de7f61c84ec7c8db22d48cd900fb85 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -204,6 +204,12 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val, do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0) #define dynamic_dev_dbg(dev, fmt, ...) \ do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0) +#define dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) \ + do { if (0) \ + print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, \ + rowsize, groupsize, buf, len, ascii); \ + } while (0) #endif #endif diff --git a/include/linux/efi.h b/include/linux/efi.h index bd3837022307ac34271054b4024f8ec6bab09e5a..d87acf62958e207f941080c251048c9215df834e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1579,9 +1579,22 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, struct efi_boot_memmap *map); +efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg, + unsigned long size, unsigned long align, + unsigned long *addr, unsigned long min); + +static inline efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, unsigned long size, unsigned long align, - unsigned long *addr); + unsigned long *addr) +{ + /* + * Don't allocate at 0x0. It will confuse code that + * checks pointers against NULL. Skip the first 8 + * bytes so we start at a nice even number. + */ + return efi_low_alloc_above(sys_table_arg, size, align, addr, 0x8); +} efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, unsigned long size, unsigned long align, @@ -1592,7 +1605,8 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, unsigned long image_size, unsigned long alloc_size, unsigned long preferred_addr, - unsigned long alignment); + unsigned long alignment, + unsigned long min_addr); efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, efi_loaded_image_t *image, diff --git a/include/linux/filter.h b/include/linux/filter.h index 2ce57645f3cd4a00d8d385b7e1a05296191df476..0367a75f873b6b28510155591f68077732e4638d 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1099,7 +1099,6 @@ static inline void bpf_get_prog_name(const struct bpf_prog *prog, char *sym) #endif /* CONFIG_BPF_JIT */ -void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp); void bpf_prog_kallsyms_del_all(struct bpf_prog *fp); #define BPF_ANC BIT(15) diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index f622f7460ed8c6463871bad6c8713ace10a14614..607076207f730ab4d2637771e005ca7bc75e5096 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -20,7 +20,6 @@ #define FS_CRYPTO_BLOCK_SIZE 16 -struct fscrypt_ctx; struct fscrypt_info; struct fscrypt_str { @@ -62,18 +61,10 @@ struct fscrypt_operations { bool (*dummy_context)(struct inode *); bool (*empty_dir)(struct inode *); unsigned int max_namelen; -}; - -/* Decryption work */ -struct fscrypt_ctx { - union { - struct { - struct bio *bio; - struct work_struct work; - }; - struct list_head free_list; /* Free list */ - }; - u8 flags; /* Flags */ + bool (*has_stable_inodes)(struct super_block *sb); + void (*get_ino_and_lblk_bits)(struct super_block *sb, + int *ino_bits_ret, int *lblk_bits_ret); + bool (*inline_crypt_enabled)(struct super_block *sb); }; static inline bool fscrypt_has_encryption_key(const struct inode *inode) @@ -102,8 +93,6 @@ static inline void fscrypt_handle_d_move(struct dentry *dentry) /* crypto.c */ extern void fscrypt_enqueue_decrypt_work(struct work_struct *); -extern struct fscrypt_ctx *fscrypt_get_ctx(gfp_t); -extern void fscrypt_release_ctx(struct fscrypt_ctx *); extern struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, unsigned int len, @@ -146,6 +135,8 @@ extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg); extern int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *arg); extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg); +extern int fscrypt_register_key_removal_notifier(struct notifier_block *nb); +extern int fscrypt_unregister_key_removal_notifier(struct notifier_block *nb); /* keysetup.c */ extern int fscrypt_get_encryption_info(struct inode *); @@ -244,8 +235,6 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, /* bio.c */ extern void fscrypt_decrypt_bio(struct bio *); -extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, - struct bio *bio); extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, unsigned int); @@ -295,16 +284,6 @@ static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work) { } -static inline struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags) -{ - return ERR_PTR(-EOPNOTSUPP); -} - -static inline void fscrypt_release_ctx(struct fscrypt_ctx *ctx) -{ - return; -} - static inline struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, unsigned int len, unsigned int offs, @@ -410,6 +389,18 @@ static inline int fscrypt_ioctl_get_key_status(struct file *filp, return -EOPNOTSUPP; } +static inline int fscrypt_register_key_removal_notifier( + struct notifier_block *nb) +{ + return 0; +} + +static inline int fscrypt_unregister_key_removal_notifier( + struct notifier_block *nb) +{ + return 0; +} + /* keysetup.c */ static inline int fscrypt_get_encryption_info(struct inode *inode) { @@ -484,11 +475,6 @@ static inline void fscrypt_decrypt_bio(struct bio *bio) { } -static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, - struct bio *bio) -{ -} - static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, sector_t pblk, unsigned int len) { @@ -558,6 +544,65 @@ static inline void fscrypt_set_ops(struct super_block *sb, #endif /* !CONFIG_FS_ENCRYPTION */ +/* inline_crypt.c */ +#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT +extern bool fscrypt_inode_uses_inline_crypto(const struct inode *inode); + +extern bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode); + +extern int fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, + u64 first_lblk, gfp_t gfp_mask); + +extern int fscrypt_set_bio_crypt_ctx_bh(struct bio *bio, + const struct buffer_head *first_bh, + gfp_t gfp_mask); + +extern bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, + u64 next_lblk); + +extern bool fscrypt_mergeable_bio_bh(struct bio *bio, + const struct buffer_head *next_bh); + +#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ +static inline bool fscrypt_inode_uses_inline_crypto(const struct inode *inode) +{ + return false; +} + +static inline bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode) +{ + return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); +} + +static inline int fscrypt_set_bio_crypt_ctx(struct bio *bio, + const struct inode *inode, + u64 first_lblk, gfp_t gfp_mask) +{ + return 0; +} + +static inline int fscrypt_set_bio_crypt_ctx_bh( + struct bio *bio, + const struct buffer_head *first_bh, + gfp_t gfp_mask) +{ + return 0; +} + +static inline bool fscrypt_mergeable_bio(struct bio *bio, + const struct inode *inode, + u64 next_lblk) +{ + return true; +} + +static inline bool fscrypt_mergeable_bio_bh(struct bio *bio, + const struct buffer_head *next_bh) +{ + return true; +} +#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ + /** * fscrypt_require_key - require an inode's encryption key * @inode: the inode we need the key for diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 6ae05b9ce359740dbebb426d0dd1ba770e175214..766ff9bb58760bd5ce6342567d38435710b0cbed 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -71,16 +71,38 @@ struct fwnode_reference_args { * links to all the suppliers of the device that are available at * the time this function is called. The function must NOT stop * at the first failed device link if other unlinked supplier - * devices are present in the system. If some suppliers are not - * yet available, this function will be called again when other + * devices are present in the system. This is necessary for the + * driver/bus sync_state() callbacks to work correctly. + * + * For example, say Device-C depends on suppliers Device-S1 and + * Device-S2 and the dependency is listed in that order in the + * firmware. Say, S1 gets populated from the firmware after + * late_initcall_sync(). Say S2 is populated and probed way + * before that in device_initcall(). When C is populated, if this + * add_links() function doesn't continue past a "failed linking to + * S1" and continue linking C to S2, then S2 will get a + * sync_state() callback before C is probed. This is because from + * the perspective of S2, C was never a consumer when its + * sync_state() evaluation is done. To avoid this, the add_links() + * function has to go through all available suppliers of the + * device (that corresponds to this fwnode) and link to them + * before returning. + * + * If some suppliers are not yet available (indicated by an error + * return value), this function will be called again when other * devices are added to allow creating device links to any newly * available suppliers. * * Return 0 if device links have been successfully created to all - * the suppliers of this device or if the supplier information is - * not known. Return an error if and only if the supplier - * information is known but some of the suppliers are not yet - * available to create device links to. + * the suppliers this device needs to create device links to or if + * the supplier information is not known. + * + * Return -ENODEV if and only if the suppliers needed for probing + * the device are not yet available to create device links to. + * + * Return -EAGAIN if there are suppliers that need to be linked to + * that are not yet available but none of those suppliers are + * necessary for probing this device. */ struct fwnode_operations { struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); diff --git a/include/linux/gfp.h b/include/linux/gfp.h index fb07b503dc453ddfe16c5f0f959d46be01ad55ba..61f2f6ff94673b0a74d2d7705d87373bfba74fe5 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -325,6 +325,29 @@ static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) return !!(gfp_flags & __GFP_DIRECT_RECLAIM); } +/** + * gfpflags_normal_context - is gfp_flags a normal sleepable context? + * @gfp_flags: gfp_flags to test + * + * Test whether @gfp_flags indicates that the allocation is from the + * %current context and allowed to sleep. + * + * An allocation being allowed to block doesn't mean it owns the %current + * context. When direct reclaim path tries to allocate memory, the + * allocation context is nested inside whatever %current was doing at the + * time of the original allocation. The nested allocation may be allowed + * to block but modifying anything %current owns can corrupt the outer + * context's expectations. + * + * %true result from this function indicates that the allocation context + * can sleep and use anything that's associated with %current. + */ +static inline bool gfpflags_normal_context(const gfp_t gfp_flags) +{ + return (gfp_flags & (__GFP_DIRECT_RECLAIM | __GFP_MEMALLOC)) == + __GFP_DIRECT_RECLAIM; +} + #ifdef CONFIG_HIGHMEM #define OPT_ZONE_HIGHMEM ZONE_HIGHMEM #else diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index f8245d67f07089774bca10017df85fb82ee39835..5dd9c982e2cbee6d10aa42fbcd888d702e6751cc 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -201,6 +201,14 @@ struct gpio_irq_chip { */ bool threaded; + /** + * @init_hw: optional routine to initialize hardware before + * an IRQ chip will be added. This is quite useful when + * a particular driver wants to clear IRQ related registers + * in order to avoid undesired events. + */ + int (*init_hw)(struct gpio_chip *chip); + /** * @init_valid_mask: optional routine to initialize @valid_mask, to be * used if not all GPIO lines are valid interrupts. Sometimes some diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 2e55e4cdbd8aaf2fb6f1e9220ba2a8f3d6285de5..a367ead4bf4bb16e0c41544335031f85aa2d61b3 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -29,7 +29,6 @@ struct macvlan_dev { netdev_features_t set_features; enum macvlan_mode mode; u16 flags; - int nest_level; unsigned int macaddr_count; #ifdef CONFIG_NET_POLL_CONTROLLER struct netpoll *netpoll; diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 06faa066496f92fd381ae093568d640d3dfd1a1f..ec7e4bd07f825539c21c74e87bd2f675a72fac9a 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -223,6 +223,7 @@ struct team { atomic_t count_pending; struct delayed_work dw; } mcast_rejoin; + struct lock_class_key team_lock_key; long mode_priv[TEAM_MODE_PRIV_LONGS]; }; diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 244278d5c222d250816256ac455d868f415ecc99..b05e855f1ddd4f2ea1cb0282ad754a7a50f826fe 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -182,7 +182,6 @@ struct vlan_dev_priv { #ifdef CONFIG_NET_POLL_CONTROLLER struct netpoll *netpoll; #endif - unsigned int nest_level; }; static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev) @@ -221,11 +220,6 @@ extern void vlan_vids_del_by_dev(struct net_device *dev, extern bool vlan_uses_dev(const struct net_device *dev); -static inline int vlan_get_encap_level(struct net_device *dev) -{ - BUG_ON(!is_vlan_dev(dev)); - return vlan_dev_priv(dev)->nest_level; -} #else static inline struct net_device * __vlan_find_dev_deep_rcu(struct net_device *real_dev, @@ -295,11 +289,6 @@ static inline bool vlan_uses_dev(const struct net_device *dev) { return false; } -static inline int vlan_get_encap_level(struct net_device *dev) -{ - BUG(); - return 0; -} #endif /** diff --git a/include/linux/keyslot-manager.h b/include/linux/keyslot-manager.h new file mode 100644 index 0000000000000000000000000000000000000000..0777ade7907c4a8c03e2358ccec2458cb84d069b --- /dev/null +++ b/include/linux/keyslot-manager.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + */ + +#include + +#ifdef CONFIG_BLOCK + +#ifndef __LINUX_KEYSLOT_MANAGER_H +#define __LINUX_KEYSLOT_MANAGER_H + +/** + * struct keyslot_mgmt_ll_ops - functions to manage keyslots in hardware + * @keyslot_program: Program the specified key and algorithm into the + * specified slot in the inline encryption hardware. + * @keyslot_evict: Evict key from the specified keyslot in the hardware. + * The key, crypto_mode and data_unit_size are also passed + * down so that e.g. dm layers can evict keys from + * the devices that they map over. + * Returns 0 on success, -errno otherwise. + * @crypto_mode_supported: Check whether a crypto_mode and data_unit_size + * combo is supported. + * @keyslot_find: Returns the slot number that matches the key, + * or -ENOKEY if no match found, or -errno on + * error. + * + * This structure should be provided by storage device drivers when they set up + * a keyslot manager - this structure holds the function ptrs that the keyslot + * manager will use to manipulate keyslots in the hardware. + */ +struct keyslot_mgmt_ll_ops { + int (*keyslot_program)(void *ll_priv_data, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size, + unsigned int slot); + int (*keyslot_evict)(void *ll_priv_data, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size, + unsigned int slot); + bool (*crypto_mode_supported)(void *ll_priv_data, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size); + int (*keyslot_find)(void *ll_priv_data, const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size); +}; + +#ifdef CONFIG_BLK_INLINE_ENCRYPTION +struct keyslot_manager; + +extern struct keyslot_manager *keyslot_manager_create(unsigned int num_slots, + const struct keyslot_mgmt_ll_ops *ksm_ops, + void *ll_priv_data); + +extern int +keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm, + const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size); + +extern void keyslot_manager_get_slot(struct keyslot_manager *ksm, + unsigned int slot); + +extern void keyslot_manager_put_slot(struct keyslot_manager *ksm, + unsigned int slot); + +extern bool +keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size); + +extern bool +keyslot_manager_rq_crypto_mode_supported(struct request_queue *q, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size); + +extern int keyslot_manager_evict_key(struct keyslot_manager *ksm, + const u8 *key, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size); + +extern void keyslot_manager_destroy(struct keyslot_manager *ksm); + +#else /* CONFIG_BLK_INLINE_ENCRYPTION */ + +static inline bool +keyslot_manager_rq_crypto_mode_supported(struct request_queue *q, + enum blk_crypto_mode_num crypto_mode, + unsigned int data_unit_size) +{ + return false; +} +#endif /* CONFIG_BLK_INLINE_ENCRYPTION */ + +#endif /* __LINUX_KEYSLOT_MANAGER_H */ + +#endif /* CONFIG_BLOCK */ diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h index ad24554f11f969d87762d460341622235f9a79ae..75f880c25bb86cacd9370a61bd2db66c9427296f 100644 --- a/include/linux/micrel_phy.h +++ b/include/linux/micrel_phy.h @@ -31,7 +31,7 @@ #define PHY_ID_KSZ886X 0x00221430 #define PHY_ID_KSZ8863 0x00221435 -#define PHY_ID_KSZ8795 0x00221550 +#define PHY_ID_KSZ87XX 0x00221550 #define PHY_ID_KSZ9477 0x00221631 diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 138c50d5a3533d7ad0b2c8757e9fff08c9b1b388..0836fe232f975718532f89b5b6e23bf79f2272dc 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -1545,9 +1545,8 @@ struct mlx5_ifc_extended_dest_format_bits { }; union mlx5_ifc_dest_format_struct_flow_counter_list_auto_bits { - struct mlx5_ifc_dest_format_struct_bits dest_format_struct; + struct mlx5_ifc_extended_dest_format_bits extended_dest_format; struct mlx5_ifc_flow_counter_list_bits flow_counter_list; - u8 reserved_at_0[0x40]; }; struct mlx5_ifc_fte_match_param_bits { diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 5714fd35a83c43ca40c854ef5b1ddf8350da8aef..3dbed7e030df6754d227473e5749434538075257 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -318,7 +318,7 @@ struct pcmcia_device_id { #define INPUT_DEVICE_ID_LED_MAX 0x0f #define INPUT_DEVICE_ID_SND_MAX 0x07 #define INPUT_DEVICE_ID_FF_MAX 0x7f -#define INPUT_DEVICE_ID_SW_MAX 0x0f +#define INPUT_DEVICE_ID_SW_MAX 0x20 #define INPUT_DEVICE_ID_PROP_MAX 0x1f #define INPUT_DEVICE_ID_MATCH_BUS 1 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9eda1c31d1f77956ac3fc382be25ac44906e83bc..c20f190b4c189615c4eebaa84da6b89c1077f223 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -925,6 +925,7 @@ struct dev_ifalias { struct devlink; struct tlsdev_ops; + /* * This structure defines the management hooks for network devices. * The following hooks can be defined; unless noted otherwise, they are @@ -1421,7 +1422,6 @@ struct net_device_ops { void (*ndo_dfwd_del_station)(struct net_device *pdev, void *priv); - int (*ndo_get_lock_subclass)(struct net_device *dev); int (*ndo_set_tx_maxrate)(struct net_device *dev, int queue_index, u32 maxrate); @@ -1649,6 +1649,8 @@ enum netdev_priv_flags { * @perm_addr: Permanent hw address * @addr_assign_type: Hw address assignment type * @addr_len: Hardware address length + * @upper_level: Maximum depth level of upper devices. + * @lower_level: Maximum depth level of lower devices. * @neigh_priv_len: Used in neigh_alloc() * @dev_id: Used to differentiate devices that share * the same link layer address @@ -1758,9 +1760,13 @@ enum netdev_priv_flags { * @phydev: Physical device may attach itself * for hardware timestamping * @sfp_bus: attached &struct sfp_bus structure. - * - * @qdisc_tx_busylock: lockdep class annotating Qdisc->busylock spinlock - * @qdisc_running_key: lockdep class annotating Qdisc->running seqcount + * @qdisc_tx_busylock_key: lockdep class annotating Qdisc->busylock + spinlock + * @qdisc_running_key: lockdep class annotating Qdisc->running seqcount + * @qdisc_xmit_lock_key: lockdep class annotating + * netdev_queue->_xmit_lock spinlock + * @addr_list_lock_key: lockdep class annotating + * net_device->addr_list_lock spinlock * * @proto_down: protocol port state information can be sent to the * switch driver and used to set the phys state of the @@ -1875,6 +1881,8 @@ struct net_device { unsigned char perm_addr[MAX_ADDR_LEN]; unsigned char addr_assign_type; unsigned char addr_len; + unsigned char upper_level; + unsigned char lower_level; unsigned short neigh_priv_len; unsigned short dev_id; unsigned short dev_port; @@ -2045,8 +2053,10 @@ struct net_device { #endif struct phy_device *phydev; struct sfp_bus *sfp_bus; - struct lock_class_key *qdisc_tx_busylock; - struct lock_class_key *qdisc_running_key; + struct lock_class_key qdisc_tx_busylock_key; + struct lock_class_key qdisc_running_key; + struct lock_class_key qdisc_xmit_lock_key; + struct lock_class_key addr_list_lock_key; bool proto_down; unsigned wol_enabled:1; }; @@ -2124,23 +2134,6 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev, f(dev, &dev->_tx[i], arg); } -#define netdev_lockdep_set_classes(dev) \ -{ \ - static struct lock_class_key qdisc_tx_busylock_key; \ - static struct lock_class_key qdisc_running_key; \ - static struct lock_class_key qdisc_xmit_lock_key; \ - static struct lock_class_key dev_addr_list_lock_key; \ - unsigned int i; \ - \ - (dev)->qdisc_tx_busylock = &qdisc_tx_busylock_key; \ - (dev)->qdisc_running_key = &qdisc_running_key; \ - lockdep_set_class(&(dev)->addr_list_lock, \ - &dev_addr_list_lock_key); \ - for (i = 0; i < (dev)->num_tx_queues; i++) \ - lockdep_set_class(&(dev)->_tx[i]._xmit_lock, \ - &qdisc_xmit_lock_key); \ -} - u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev); struct netdev_queue *netdev_core_pick_tx(struct net_device *dev, @@ -3139,6 +3132,7 @@ static inline void netif_stop_queue(struct net_device *dev) } void netif_tx_stop_all_queues(struct net_device *dev); +void netdev_update_lockdep_key(struct net_device *dev); static inline bool netif_tx_queue_stopped(const struct netdev_queue *dev_queue) { @@ -4056,16 +4050,6 @@ static inline void netif_addr_lock(struct net_device *dev) spin_lock(&dev->addr_list_lock); } -static inline void netif_addr_lock_nested(struct net_device *dev) -{ - int subclass = SINGLE_DEPTH_NESTING; - - if (dev->netdev_ops->ndo_get_lock_subclass) - subclass = dev->netdev_ops->ndo_get_lock_subclass(dev); - - spin_lock_nested(&dev->addr_list_lock, subclass); -} - static inline void netif_addr_lock_bh(struct net_device *dev) { spin_lock_bh(&dev->addr_list_lock); @@ -4329,6 +4313,16 @@ int netdev_master_upper_dev_link(struct net_device *dev, struct netlink_ext_ack *extack); void netdev_upper_dev_unlink(struct net_device *dev, struct net_device *upper_dev); +int netdev_adjacent_change_prepare(struct net_device *old_dev, + struct net_device *new_dev, + struct net_device *dev, + struct netlink_ext_ack *extack); +void netdev_adjacent_change_commit(struct net_device *old_dev, + struct net_device *new_dev, + struct net_device *dev); +void netdev_adjacent_change_abort(struct net_device *old_dev, + struct net_device *new_dev, + struct net_device *dev); void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); void *netdev_lower_dev_get_private(struct net_device *dev, struct net_device *lower_dev); @@ -4340,7 +4334,6 @@ void netdev_lower_state_changed(struct net_device *lower_dev, extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly; void netdev_rss_key_fill(void *buffer, size_t len); -int dev_get_nest_level(struct net_device *dev); int skb_checksum_help(struct sk_buff *skb); int skb_crc32c_csum_help(struct sk_buff *skb); int skb_csum_hwoffload_help(struct sk_buff *skb, diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h index 682fd465df060c0ac2cde1f67b7b6c11090dd17f..cfce186f0c4e0ecd8be7c211e8a3fbb95c963242 100644 --- a/include/linux/page_ext.h +++ b/include/linux/page_ext.h @@ -18,7 +18,7 @@ struct page_ext_operations { enum page_ext_flags { PAGE_EXT_OWNER, - PAGE_EXT_OWNER_ACTIVE, + PAGE_EXT_OWNER_ALLOCATED, #if defined(CONFIG_IDLE_PAGE_TRACKING) && !defined(CONFIG_64BIT) PAGE_EXT_YOUNG, PAGE_EXT_IDLE, @@ -36,6 +36,7 @@ struct page_ext { unsigned long flags; }; +extern unsigned long page_ext_size; extern void pgdat_page_ext_init(struct pglist_data *pgdat); #ifdef CONFIG_SPARSEMEM @@ -52,6 +53,13 @@ static inline void page_ext_init(void) struct page_ext *lookup_page_ext(const struct page *page); +static inline struct page_ext *page_ext_next(struct page_ext *curr) +{ + void *next = curr; + next += page_ext_size; + return next; +} + #else /* !CONFIG_PAGE_EXTENSION */ struct page_ext; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index a24e32410915ddb0430afc3c6f6b9c8638ff2a4a..a7565ea449388a6d02e2fb27265c778c667387cb 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -292,7 +292,7 @@ struct pmu { * -EBUSY -- @event is for this PMU but PMU temporarily unavailable * -EINVAL -- @event is for this PMU but @event is not valid * -EOPNOTSUPP -- @event is for this PMU, @event is valid, but not supported - * -EACCESS -- @event is for this PMU, @event is valid, but no privilidges + * -EACCES -- @event is for this PMU, @event is valid, but no privileges * * 0 -- @event is for this PMU and valid * diff --git a/include/linux/platform_data/dma-imx-sdma.h b/include/linux/platform_data/dma-imx-sdma.h index 6eaa53cef0bd228b8a0d7bb2b3938ff04c548f95..30e676b36b247a595c39e98d7c59bdaa7e6eb233 100644 --- a/include/linux/platform_data/dma-imx-sdma.h +++ b/include/linux/platform_data/dma-imx-sdma.h @@ -51,7 +51,10 @@ struct sdma_script_start_addrs { /* End of v2 array */ s32 zcanfd_2_mcu_addr; s32 zqspi_2_mcu_addr; + s32 mcu_2_ecspi_addr; /* End of v3 array */ + s32 mcu_2_zqspi_addr; + /* End of v4 array */ }; /** diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 222c3e01397c17674ea6811aaefc330c3a3077a1..ebf5ef17cc2ae3f45a1ff5379c387e2d0bc9a089 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -34,8 +34,6 @@ enum pm_qos_flags_status { #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 -#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE 0 -#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE (-1) #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) @@ -54,8 +52,6 @@ struct pm_qos_flags_request { enum dev_pm_qos_req_type { DEV_PM_QOS_RESUME_LATENCY = 1, DEV_PM_QOS_LATENCY_TOLERANCE, - DEV_PM_QOS_MIN_FREQUENCY, - DEV_PM_QOS_MAX_FREQUENCY, DEV_PM_QOS_FLAGS, }; @@ -97,14 +93,10 @@ struct pm_qos_flags { struct dev_pm_qos { struct pm_qos_constraints resume_latency; struct pm_qos_constraints latency_tolerance; - struct pm_qos_constraints min_frequency; - struct pm_qos_constraints max_frequency; struct pm_qos_flags flags; struct dev_pm_qos_request *resume_latency_req; struct dev_pm_qos_request *latency_tolerance_req; struct dev_pm_qos_request *flags_req; - struct dev_pm_qos_request *min_frequency_req; - struct dev_pm_qos_request *max_frequency_req; }; /* Action requested to pm_qos_update_target */ @@ -199,10 +191,6 @@ static inline s32 dev_pm_qos_read_value(struct device *dev, switch (type) { case DEV_PM_QOS_RESUME_LATENCY: return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; - case DEV_PM_QOS_MIN_FREQUENCY: - return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; - case DEV_PM_QOS_MAX_FREQUENCY: - return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; default: WARN_ON(1); return 0; @@ -267,4 +255,48 @@ static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) } #endif +#define FREQ_QOS_MIN_DEFAULT_VALUE 0 +#define FREQ_QOS_MAX_DEFAULT_VALUE (-1) + +enum freq_qos_req_type { + FREQ_QOS_MIN = 1, + FREQ_QOS_MAX, +}; + +struct freq_constraints { + struct pm_qos_constraints min_freq; + struct blocking_notifier_head min_freq_notifiers; + struct pm_qos_constraints max_freq; + struct blocking_notifier_head max_freq_notifiers; +}; + +struct freq_qos_request { + enum freq_qos_req_type type; + struct plist_node pnode; + struct freq_constraints *qos; +}; + +static inline int freq_qos_request_active(struct freq_qos_request *req) +{ + return !IS_ERR_OR_NULL(req->qos); +} + +void freq_constraints_init(struct freq_constraints *qos); + +s32 freq_qos_read_value(struct freq_constraints *qos, + enum freq_qos_req_type type); + +int freq_qos_add_request(struct freq_constraints *qos, + struct freq_qos_request *req, + enum freq_qos_req_type type, s32 value); +int freq_qos_update_request(struct freq_qos_request *req, s32 new_value); +int freq_qos_remove_request(struct freq_qos_request *req); + +int freq_qos_add_notifier(struct freq_constraints *qos, + enum freq_qos_req_type type, + struct notifier_block *notifier); +int freq_qos_remove_notifier(struct freq_constraints *qos, + enum freq_qos_req_type type, + struct notifier_block *notifier); + #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 16c499ca096bf0ed6a29f380b660a93c90e32538..2f35afc13de3357d67e91bdc74638813f6f22b3f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -223,6 +223,7 @@ extern long schedule_timeout_uninterruptible(long timeout); extern long schedule_timeout_idle(long timeout); asmlinkage void schedule(void); extern void schedule_preempt_disabled(void); +asmlinkage void preempt_schedule_irq(void); extern int __must_check io_schedule_prepare(void); extern void io_schedule_finish(int token); diff --git a/include/linux/security.h b/include/linux/security.h index a8d59d612d274bdb5df8cbd13245b35fc2e08908..9df7547afc0cb783883b5c5c7b32b2956a650d7a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -105,6 +105,7 @@ enum lockdown_reason { LOCKDOWN_NONE, LOCKDOWN_MODULE_SIGNATURE, LOCKDOWN_DEV_MEM, + LOCKDOWN_EFI_TEST, LOCKDOWN_KEXEC, LOCKDOWN_HIBERNATION, LOCKDOWN_PCI_ACCESS, diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 4351577b14d704fbdb429084b792fe298782147e..64a395c7f6895ce4dc439571de2eec8673b393e4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1354,7 +1354,8 @@ static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, const struct flowi6 return skb->hash; } -__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb); +__u32 skb_get_hash_perturb(const struct sk_buff *skb, + const siphash_key_t *perturb); static inline __u32 skb_get_hash_raw(const struct sk_buff *skb) { @@ -1494,6 +1495,19 @@ static inline int skb_queue_empty(const struct sk_buff_head *list) return list->next == (const struct sk_buff *) list; } +/** + * skb_queue_empty_lockless - check if a queue is empty + * @list: queue head + * + * Returns true if the queue is empty, false otherwise. + * This variant can be used in lockless contexts. + */ +static inline bool skb_queue_empty_lockless(const struct sk_buff_head *list) +{ + return READ_ONCE(list->next) == (const struct sk_buff *) list; +} + + /** * skb_queue_is_last - check if skb is the last entry in the queue * @list: queue head @@ -1847,9 +1861,11 @@ static inline void __skb_insert(struct sk_buff *newsk, struct sk_buff *prev, struct sk_buff *next, struct sk_buff_head *list) { - newsk->next = next; - newsk->prev = prev; - next->prev = prev->next = newsk; + /* see skb_queue_empty_lockless() for the opposite READ_ONCE() */ + WRITE_ONCE(newsk->next, next); + WRITE_ONCE(newsk->prev, prev); + WRITE_ONCE(next->prev, newsk); + WRITE_ONCE(prev->next, newsk); list->qlen++; } @@ -1860,11 +1876,11 @@ static inline void __skb_queue_splice(const struct sk_buff_head *list, struct sk_buff *first = list->next; struct sk_buff *last = list->prev; - first->prev = prev; - prev->next = first; + WRITE_ONCE(first->prev, prev); + WRITE_ONCE(prev->next, first); - last->next = next; - next->prev = last; + WRITE_ONCE(last->next, next); + WRITE_ONCE(next->prev, last); } /** @@ -2005,8 +2021,8 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) next = skb->next; prev = skb->prev; skb->next = skb->prev = NULL; - next->prev = prev; - prev->next = next; + WRITE_ONCE(next->prev, prev); + WRITE_ONCE(prev->next, next); } /** @@ -3510,8 +3526,9 @@ int skb_ensure_writable(struct sk_buff *skb, int write_len); int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci); int skb_vlan_pop(struct sk_buff *skb); int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); -int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto); -int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto); +int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, + int mac_len); +int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len); int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse); int skb_mpls_dec_ttl(struct sk_buff *skb); struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy, diff --git a/include/linux/soc/qcom/irq.h b/include/linux/soc/qcom/irq.h index 59a459e0ee1294cc9e59a758e3f3ecb02231e79d..fcb799c887b9478db1937983d39d2f79553bac3b 100644 --- a/include/linux/soc/qcom/irq.h +++ b/include/linux/soc/qcom/irq.h @@ -3,7 +3,7 @@ #ifndef __QCOM_IRQ_H #define __QCOM_IRQ_H -struct irq_domain; +#include #define GPIO_NO_WAKE_IRQ ~0U @@ -21,14 +21,14 @@ struct irq_domain; /** * irq_domain_qcom_handle_wakeup: Return if the domain handles interrupt * configuration - * @d: irq domain + * @parent: irq domain * * This QCOM specific irq domain call returns if the interrupt controller * requires the interrupt be masked at the child interrupt controller. */ -static inline bool irq_domain_qcom_handle_wakeup(struct irq_domain *d) +static inline bool irq_domain_qcom_handle_wakeup(struct irq_domain *parent) { - return (d->flags & IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP); + return (parent->flags & IRQ_DOMAIN_FLAG_QCOM_PDC_WAKEUP); } #endif diff --git a/include/linux/socket.h b/include/linux/socket.h index fc0bed59fc84ef8e6631d3c275853d52a46f84aa..4049d9755cf198bdda600a61485b36a888b9d879 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -263,7 +263,7 @@ struct ucred { #define PF_MAX AF_MAX /* Maximum queue length specifiable by listen. */ -#define SOMAXCONN 128 +#define SOMAXCONN 4096 /* Flags we can use with send/ and recv. Added those for 1003.1g not all are supported yet diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h index 87d27e13d8859742044849854288a7f5bec76dfe..d796058cdff2a82b0c65450f988f29683513cea8 100644 --- a/include/linux/sunrpc/bc_xprt.h +++ b/include/linux/sunrpc/bc_xprt.h @@ -64,6 +64,11 @@ static inline int xprt_setup_backchannel(struct rpc_xprt *xprt, return 0; } +static inline void xprt_destroy_backchannel(struct rpc_xprt *xprt, + unsigned int max_reqs) +{ +} + static inline bool svc_is_backchannel(const struct svc_rqst *rqstp) { return false; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 5420817ed317ebf3642758dd950d3994458eb977..fa7ee503fb76326d181d844aad22700bd85bf7fa 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -196,9 +196,9 @@ struct bin_attribute { .size = _size, \ } -#define __BIN_ATTR_WO(_name) { \ +#define __BIN_ATTR_WO(_name, _size) { \ .attr = { .name = __stringify(_name), .mode = 0200 }, \ - .store = _name##_store, \ + .write = _name##_write, \ .size = _size, \ } diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 99617e528ea2906b234cadc1fb3d79d0efd46331..668e25a76d69809b5ade30f5774a4c62833b8b9b 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -393,7 +393,7 @@ struct tcp_sock { /* fastopen_rsk points to request_sock that resulted in this big * socket. Used to retransmit SYNACKs etc. */ - struct request_sock *fastopen_rsk; + struct request_sock __rcu *fastopen_rsk; u32 *saved_syn; }; @@ -447,8 +447,8 @@ static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk) static inline bool tcp_passive_fastopen(const struct sock *sk) { - return (sk->sk_state == TCP_SYN_RECV && - tcp_sk(sk)->fastopen_rsk != NULL); + return sk->sk_state == TCP_SYN_RECV && + rcu_access_pointer(tcp_sk(sk)->fastopen_rsk) != NULL; } static inline void fastopen_queue_tune(struct sock *sk, int backlog) diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index 4c7781f4b29b6491204cb14cd7ce829a0f867588..07875ccc7bb50e9ec44a1886e4649aa27be1a2f8 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -48,7 +48,6 @@ struct virtio_vsock_sock { struct virtio_vsock_pkt { struct virtio_vsock_hdr hdr; - struct work_struct work; struct list_head list; /* socket refcnt not held, only use for cancellation */ struct vsock_sock *vsk; diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 5921599b6dc4f5f573ebf28a3a5553e0e391eda0..86eecbd98e84ab78c13fbdda228b173f9bb404f5 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h @@ -230,8 +230,8 @@ static inline int xa_err(void *entry) * This structure is used either directly or via the XA_LIMIT() macro * to communicate the range of IDs that are valid for allocation. * Two common ranges are predefined for you: - * * xa_limit_32b - [0 - UINT_MAX] - * * xa_limit_31b - [0 - INT_MAX] + * * xa_limit_32b - [0 - UINT_MAX] + * * xa_limit_31b - [0 - INT_MAX] */ struct xa_limit { u32 max; diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 640aabe69450c80d5d17f0825a467f4bdbbad2eb..1168ed938f8ce9e285ac2bdd4a27d6f17360ec88 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -19,7 +19,7 @@ #include #include -#define VB2_MAX_FRAME (32) +#define VB2_MAX_FRAME (64) #define VB2_MAX_PLANES (8) /** diff --git a/include/net/bonding.h b/include/net/bonding.h index f7fe45689142150231a74247f35811ce4dd77600..1afc125014dac426c00af8807cc9f908345cbbb1 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -203,7 +203,6 @@ struct bonding { struct slave __rcu *primary_slave; struct bond_up_slave __rcu *slave_arr; /* Array of usable slaves */ bool force_primary; - u32 nest_level; s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ int (*recv_probe)(const struct sk_buff *, struct bonding *, struct slave *); @@ -239,6 +238,7 @@ struct bonding { struct dentry *debug_dir; #endif /* CONFIG_DEBUG_FS */ struct rtnl_link_stats64 bond_stats; + struct lock_class_key stats_lock_key; }; #define bond_slave_get_rcu(dev) \ diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h index 127a5c4e369914814c3004d2701ebb5ae026ca95..86e028388badc46977bf6c05bd8f718d852c14a8 100644 --- a/include/net/busy_poll.h +++ b/include/net/busy_poll.h @@ -122,7 +122,7 @@ static inline void skb_mark_napi_id(struct sk_buff *skb, static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb) { #ifdef CONFIG_NET_RX_BUSY_POLL - sk->sk_napi_id = skb->napi_id; + WRITE_ONCE(sk->sk_napi_id, skb->napi_id); #endif sk_rx_queue_set(sk, skb); } @@ -132,8 +132,8 @@ static inline void sk_mark_napi_id_once(struct sock *sk, const struct sk_buff *skb) { #ifdef CONFIG_NET_RX_BUSY_POLL - if (!sk->sk_napi_id) - sk->sk_napi_id = skb->napi_id; + if (!READ_ONCE(sk->sk_napi_id)) + WRITE_ONCE(sk->sk_napi_id, skb->napi_id); #endif } diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ff45c3e1abff820cbfa93715e681592cd32576af..4ab2c49423dcba4b42706cf523cefe4fee672da3 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5549,6 +5549,14 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, */ const char *reg_initiator_name(enum nl80211_reg_initiator initiator); +/** + * regulatory_pre_cac_allowed - check if pre-CAC allowed in the current regdom + * @wiphy: wiphy for which pre-CAC capability is checked. + * + * Pre-CAC is allowed only in some regdomains (notable ETSI). + */ +bool regulatory_pre_cac_allowed(struct wiphy *wiphy); + /** * DOC: Internal regulatory db functions * diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h index 90bd210be06075818a8ba3213006e16eb610c602..5cd12276ae21a52006debcd846c85be1b04bf596 100644 --- a/include/net/flow_dissector.h +++ b/include/net/flow_dissector.h @@ -4,6 +4,7 @@ #include #include +#include #include /** @@ -276,7 +277,7 @@ struct flow_keys_basic { struct flow_keys { struct flow_dissector_key_control control; #define FLOW_KEYS_HASH_START_FIELD basic - struct flow_dissector_key_basic basic; + struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT); struct flow_dissector_key_tags tags; struct flow_dissector_key_vlan vlan; struct flow_dissector_key_vlan cvlan; diff --git a/include/net/fq.h b/include/net/fq.h index d126b5d2026155aa7311ea82ce609122c6da45e0..2ad85e68304142fc3193e8a2c4dc1cfb4cca821a 100644 --- a/include/net/fq.h +++ b/include/net/fq.h @@ -69,7 +69,7 @@ struct fq { struct list_head backlogs; spinlock_t lock; u32 flows_cnt; - u32 perturbation; + siphash_key_t perturbation; u32 limit; u32 memory_limit; u32 memory_usage; diff --git a/include/net/fq_impl.h b/include/net/fq_impl.h index be40a4b327e3d1d51f15f29b45216b39e7d1f42e..107c0d700ed6ffd03cd1dc835f086eb989adbed3 100644 --- a/include/net/fq_impl.h +++ b/include/net/fq_impl.h @@ -108,7 +108,7 @@ static struct sk_buff *fq_tin_dequeue(struct fq *fq, static u32 fq_flow_idx(struct fq *fq, struct sk_buff *skb) { - u32 hash = skb_get_hash_perturb(skb, fq->perturbation); + u32 hash = skb_get_hash_perturb(skb, &fq->perturbation); return reciprocal_scale(hash, fq->flows_cnt); } @@ -308,7 +308,7 @@ static int fq_init(struct fq *fq, int flows_cnt) INIT_LIST_HEAD(&fq->backlogs); spin_lock_init(&fq->lock); fq->flows_cnt = max_t(u32, flows_cnt, 1); - fq->perturbation = prandom_u32(); + get_random_bytes(&fq->perturbation, sizeof(fq->perturbation)); fq->quantum = 300; fq->limit = 8192; fq->memory_limit = 16 << 20; /* 16 MBytes */ diff --git a/include/net/hwbm.h b/include/net/hwbm.h index 81643cf8a1c43ea5d7a61aba0722fd2c37e55f2c..c81444611a228e51413fd162a67b2bec44400012 100644 --- a/include/net/hwbm.h +++ b/include/net/hwbm.h @@ -21,9 +21,13 @@ void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf); int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp); int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num); #else -void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {} -int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; } -int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num) +static inline void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {} + +static inline int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) +{ return 0; } + +static inline int hwbm_pool_add(struct hwbm_pool *bm_pool, + unsigned int buf_num) { return 0; } #endif /* CONFIG_HWBM */ #endif /* _HWBM_H */ diff --git a/include/net/ip.h b/include/net/ip.h index 95bb77f95bcc37404c143f7176117c72c2023d27..a2c61c36dc4afc2c2e334eeb2174f9e5636a106e 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -185,7 +185,7 @@ static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter) } struct ip_frag_state { - struct iphdr *iph; + bool DF; unsigned int hlen; unsigned int ll_rs; unsigned int mtu; @@ -196,7 +196,7 @@ struct ip_frag_state { }; void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs, - unsigned int mtu, struct ip_frag_state *state); + unsigned int mtu, bool DF, struct ip_frag_state *state); struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state); diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 3759167f91f5643ea5a192eb7e82ce3a34e9e91b..078887c8c586ad3fba436261462118ad9c47cc81 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -889,6 +889,7 @@ struct netns_ipvs { struct delayed_work defense_work; /* Work handler */ int drop_rate; int drop_counter; + int old_secure_tcp; atomic_t dropentry; /* locks in ctl.c */ spinlock_t dropentry_lock; /* drop entry handling */ diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index df528a6235487d3678ffdccb28facf977a1e7098..ea985aa7a6c5e64b6802c2399ad47db23fdbd9bf 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -104,7 +104,7 @@ void llc_sk_reset(struct sock *sk); /* Access to a connection */ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb); -int llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); +void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb); void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit); void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit); diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index f8712bbeb2e039657e5cf8d37b15511de8c9c694..c7e15a213ef2fe547b8dfc4c8e1638bd2b5b499b 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -52,6 +52,9 @@ struct bpf_prog; #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS) struct net { + /* First cache line can be often dirtied. + * Do not place here read-mostly fields. + */ refcount_t passive; /* To decide when the network * namespace should be freed. */ @@ -60,7 +63,13 @@ struct net { */ spinlock_t rules_mod_lock; - u32 hash_mix; + unsigned int dev_unreg_count; + + unsigned int dev_base_seq; /* protected by rtnl_mutex */ + int ifindex; + + spinlock_t nsid_lock; + atomic_t fnhe_genid; struct list_head list; /* list of network namespaces */ struct list_head exit_list; /* To linked to call pernet exit @@ -76,11 +85,11 @@ struct net { #endif struct user_namespace *user_ns; /* Owning user namespace */ struct ucounts *ucounts; - spinlock_t nsid_lock; struct idr netns_ids; struct ns_common ns; + struct list_head dev_base_head; struct proc_dir_entry *proc_net; struct proc_dir_entry *proc_net_stat; @@ -93,17 +102,18 @@ struct net { struct uevent_sock *uevent_sock; /* uevent socket */ - struct list_head dev_base_head; struct hlist_head *dev_name_head; struct hlist_head *dev_index_head; - unsigned int dev_base_seq; /* protected by rtnl_mutex */ - int ifindex; - unsigned int dev_unreg_count; + /* Note that @hash_mix can be read millions times per second, + * it is critical that it is on a read_mostly cache line. + */ + u32 hash_mix; + + struct net_device *loopback_dev; /* The loopback */ /* core fib_rules */ struct list_head rules_ops; - struct net_device *loopback_dev; /* The loopback */ struct netns_core core; struct netns_mib mib; struct netns_packet packet; @@ -171,7 +181,6 @@ struct net { struct sock *crypto_nlsk; #endif struct sock *diag_nlsk; - atomic_t fnhe_genid; } __randomize_layout; #include @@ -333,7 +342,7 @@ static inline struct net *read_pnet(const possible_net_t *pnet) #define __net_initconst __initconst #endif -int peernet2id_alloc(struct net *net, struct net *peer); +int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp); int peernet2id(struct net *net, struct net *peer); bool peernet_has_id(struct net *net, struct net *peer); struct net *get_net_ns_by_id(struct net *net, int id); diff --git a/include/net/request_sock.h b/include/net/request_sock.h index fd178d58fa84e7ae7abdeff5be2ba7b1ec790889..cf8b33213bbc283348fb7470c1ce8fd55cd9d508 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -185,7 +185,7 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, static inline bool reqsk_queue_empty(const struct request_sock_queue *queue) { - return queue->rskq_accept_head == NULL; + return READ_ONCE(queue->rskq_accept_head) == NULL; } static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue *queue, @@ -197,7 +197,7 @@ static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue req = queue->rskq_accept_head; if (req) { sk_acceptq_removed(parent); - queue->rskq_accept_head = req->dl_next; + WRITE_ONCE(queue->rskq_accept_head, req->dl_next); if (queue->rskq_accept_head == NULL) queue->rskq_accept_tail = NULL; } diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 5d60f13d2347b4533b6b4074f920b9abe10fe4a1..3ab5c6bbb90bd56b6856faec41d07f77346c028a 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -610,4 +610,9 @@ static inline __u32 sctp_min_frag_point(struct sctp_sock *sp, __u16 datasize) return sctp_mtu_payload(sp, SCTP_DEFAULT_MINSEGMENT, datasize); } +static inline bool sctp_newsk_ready(const struct sock *sk) +{ + return sock_flag(sk, SOCK_DEAD) || sk->sk_socket; +} + #endif /* __net_sctp_h__ */ diff --git a/include/net/sock.h b/include/net/sock.h index 2c53f1a1d905409247b1bdafdfaf99d86e430cd0..8f9adcfac41bea7e46062851a25c042261323679 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -878,12 +878,17 @@ static inline bool sk_acceptq_is_full(const struct sock *sk) */ static inline int sk_stream_min_wspace(const struct sock *sk) { - return sk->sk_wmem_queued >> 1; + return READ_ONCE(sk->sk_wmem_queued) >> 1; } static inline int sk_stream_wspace(const struct sock *sk) { - return sk->sk_sndbuf - sk->sk_wmem_queued; + return READ_ONCE(sk->sk_sndbuf) - READ_ONCE(sk->sk_wmem_queued); +} + +static inline void sk_wmem_queued_add(struct sock *sk, int val) +{ + WRITE_ONCE(sk->sk_wmem_queued, sk->sk_wmem_queued + val); } void sk_stream_write_space(struct sock *sk); @@ -949,8 +954,8 @@ static inline void sk_incoming_cpu_update(struct sock *sk) { int cpu = raw_smp_processor_id(); - if (unlikely(sk->sk_incoming_cpu != cpu)) - sk->sk_incoming_cpu = cpu; + if (unlikely(READ_ONCE(sk->sk_incoming_cpu) != cpu)) + WRITE_ONCE(sk->sk_incoming_cpu, cpu); } static inline void sock_rps_record_flow_hash(__u32 hash) @@ -1207,7 +1212,7 @@ static inline void sk_refcnt_debug_release(const struct sock *sk) static inline bool __sk_stream_memory_free(const struct sock *sk, int wake) { - if (sk->sk_wmem_queued >= sk->sk_sndbuf) + if (READ_ONCE(sk->sk_wmem_queued) >= READ_ONCE(sk->sk_sndbuf)) return false; return sk->sk_prot->stream_memory_free ? @@ -1467,7 +1472,7 @@ DECLARE_STATIC_KEY_FALSE(tcp_tx_skb_cache_key); static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) { sock_set_flag(sk, SOCK_QUEUE_SHRUNK); - sk->sk_wmem_queued -= skb->truesize; + sk_wmem_queued_add(sk, -skb->truesize); sk_mem_uncharge(sk, skb->truesize); if (static_branch_unlikely(&tcp_tx_skb_cache_key) && !sk->sk_tx_skb_cache && !skb_cloned(skb)) { @@ -2014,7 +2019,7 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, struct iov_iter *fro skb->len += copy; skb->data_len += copy; skb->truesize += copy; - sk->sk_wmem_queued += copy; + sk_wmem_queued_add(sk, copy); sk_mem_charge(sk, copy); return 0; } @@ -2220,10 +2225,14 @@ static inline void sk_wake_async(const struct sock *sk, int how, int band) static inline void sk_stream_moderate_sndbuf(struct sock *sk) { - if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) { - sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued >> 1); - sk->sk_sndbuf = max_t(u32, sk->sk_sndbuf, SOCK_MIN_SNDBUF); - } + u32 val; + + if (sk->sk_userlocks & SOCK_SNDBUF_LOCK) + return; + + val = min(sk->sk_sndbuf, sk->sk_wmem_queued >> 1); + + WRITE_ONCE(sk->sk_sndbuf, max_t(u32, val, SOCK_MIN_SNDBUF)); } struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, @@ -2233,12 +2242,17 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, * sk_page_frag - return an appropriate page_frag * @sk: socket * - * If socket allocation mode allows current thread to sleep, it means its - * safe to use the per task page_frag instead of the per socket one. + * Use the per task page_frag instead of the per socket one for + * optimization when we know that we're in the normal context and owns + * everything that's associated with %current. + * + * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest + * inside other socket operations and end up recursing into sk_page_frag() + * while it's already in use. */ static inline struct page_frag *sk_page_frag(struct sock *sk) { - if (gfpflags_allow_blocking(sk->sk_allocation)) + if (gfpflags_normal_context(sk->sk_allocation)) return ¤t->task_frag; return &sk->sk_frag; @@ -2251,7 +2265,7 @@ bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag); */ static inline bool sock_writeable(const struct sock *sk) { - return refcount_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1); + return refcount_read(&sk->sk_wmem_alloc) < (READ_ONCE(sk->sk_sndbuf) >> 1); } static inline gfp_t gfp_any(void) @@ -2271,7 +2285,9 @@ static inline long sock_sndtimeo(const struct sock *sk, bool noblock) static inline int sock_rcvlowat(const struct sock *sk, int waitall, int len) { - return (waitall ? len : min_t(int, sk->sk_rcvlowat, len)) ? : 1; + int v = waitall ? len : min_t(int, READ_ONCE(sk->sk_rcvlowat), len); + + return v ?: 1; } /* Alas, with timeout socket operations are not restartable. diff --git a/include/net/tcp.h b/include/net/tcp.h index c9a3f9688223b231e5a8c90c2494ad85f3d63cfc..ab4eb5eb5d0705b815e5eec3a772d4776be8653e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -258,7 +258,7 @@ static inline bool tcp_under_memory_pressure(const struct sock *sk) mem_cgroup_under_socket_pressure(sk->sk_memcg)) return true; - return tcp_memory_pressure; + return READ_ONCE(tcp_memory_pressure); } /* * The next routines deal with comparing 32 bit unsigned ints @@ -1380,13 +1380,14 @@ static inline int tcp_win_from_space(const struct sock *sk, int space) /* Note: caller must be prepared to deal with negative returns */ static inline int tcp_space(const struct sock *sk) { - return tcp_win_from_space(sk, sk->sk_rcvbuf - sk->sk_backlog.len - + return tcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf) - + READ_ONCE(sk->sk_backlog.len) - atomic_read(&sk->sk_rmem_alloc)); } static inline int tcp_full_space(const struct sock *sk) { - return tcp_win_from_space(sk, sk->sk_rcvbuf); + return tcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf)); } extern void tcp_openreq_init_rwin(struct request_sock *req, @@ -1916,7 +1917,8 @@ static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp) static inline bool tcp_stream_memory_free(const struct sock *sk, int wake) { const struct tcp_sock *tp = tcp_sk(sk); - u32 notsent_bytes = tp->write_seq - tp->snd_nxt; + u32 notsent_bytes = READ_ONCE(tp->write_seq) - + READ_ONCE(tp->snd_nxt); return (notsent_bytes << wake) < tcp_notsent_lowat(tp); } diff --git a/include/net/virt_wifi.h b/include/net/virt_wifi.h new file mode 100644 index 0000000000000000000000000000000000000000..343e73968d419aacee6e71f5b4026eafaf806ed4 --- /dev/null +++ b/include/net/virt_wifi.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* include/net/virt_wifi.h + * + * Define the extension interface for the network data simulation + * + * Copyright (C) 2019 Google, Inc. + * + * Author: lesl@google.com + */ +#ifndef __VIRT_WIFI_H +#define __VIRT_WIFI_H + +struct virt_wifi_network_simulation { + void (*notify_device_open)(struct net_device *dev); + void (*notify_device_stop)(struct net_device *dev); + void (*notify_scan_trigger)(struct wiphy *wiphy, + struct cfg80211_scan_request *request); + int (*generate_virt_scan_result)(struct wiphy *wiphy); +}; + +int virt_wifi_register_network_simulation( + struct virt_wifi_network_simulation *ops); +int virt_wifi_unregister_network_simulation(void); +#endif + diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 335283dbe9b3d9ec8528ba6c7f11db63600060b5..373aadcfea21d302b878392bcf851ea93a6c6702 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -197,6 +197,7 @@ struct vxlan_rdst { u8 offloaded:1; __be32 remote_vni; u32 remote_ifindex; + struct net_device *remote_dev; struct list_head list; struct rcu_head rcu; struct dst_cache dst_cache; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 6a47ba85c54c1109f32db61d700d81a23790474e..e7e733add99f80f68bd7cd4fd545c7322528bf18 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -366,7 +366,7 @@ struct ib_tm_caps { struct ib_cq_init_attr { unsigned int cqe; - int comp_vector; + u32 comp_vector; u32 flags; }; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 202f4d6a434212bd9914b4b3988aeff32a66dc09..039e289f295e1a222fb938eba2e5963658c005f0 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -199,7 +199,8 @@ struct scsi_device { unsigned broken_fua:1; /* Don't set FUA bit */ unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */ - + unsigned rpm_autosuspend:1; /* Enable runtime autosuspend at device + * creation time */ atomic_t disk_events_disable_depth; /* disable depth for disk events */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 3810b340551c35d2a621c7b243dced26dd4d7c28..6bd5ed695a5e8c3aed3869dad7c712bdd3234079 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -32,6 +32,7 @@ extern int scsi_ioctl_reset(struct scsi_device *, int __user *); struct scsi_eh_save { /* saved state */ int result; + unsigned int resid_len; int eh_eflags; enum dma_data_direction data_direction; unsigned underflow; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 31e0d6ca1ebaa228091fe8a235d08392ae691c12..2c3f0c58869b555e10cddffec10205518672231a 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -486,6 +486,9 @@ struct scsi_host_template { */ unsigned int cmd_size; struct scsi_host_cmd_pool *cmd_pool; + + /* Delay for runtime autosuspend */ + int rpm_autosuspend_delay; }; /* diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h index 0fd39295b426b0306e62bd7fd5e837c578f87f1c..057d2a2d0bd05f738936b167aef23a7529f76609 100644 --- a/include/sound/hda_register.h +++ b/include/sound/hda_register.h @@ -264,6 +264,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_ML_LOUTPAY 0x20 #define AZX_REG_ML_LINPAY 0x30 +/* bit0 is reserved, with BIT(1) mapping to stream1 */ +#define ML_LOSIDV_STREAM_MASK 0xFFFE + #define ML_LCTL_SCF_MASK 0xF #define AZX_MLCTL_SPA (0x1 << 16) #define AZX_MLCTL_CPA (0x1 << 23) diff --git a/include/sound/jack.h b/include/sound/jack.h index 3b6c552f709d7262e38e403f0b53038714f395cc..19020ee43a19acc188d6cd45bd90c7dcb1b12d2c 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -58,9 +58,6 @@ enum snd_jack_types { SND_JACK_BTN_5 = 0x0200, }; -/* Keep in sync with definitions above */ -#define SND_JACK_SWITCH_TYPES 6 - struct snd_jack { struct list_head kctl_list; struct snd_card *card; diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 985a5f583de4c7f10cf161267cd554999dad4bf8..31f76b6abf712463d4355c529be55e1519ed6dc7 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -135,9 +135,9 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct link_info *li); #ifdef DEBUG -inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, - char *name, - struct asoc_simple_dai *dai) +static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, + char *name, + struct asoc_simple_dai *dai) { struct device *dev = simple_priv_to_dev(priv); @@ -167,7 +167,7 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk)); } -inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) +static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) { struct snd_soc_card *card = simple_priv_to_card(priv); struct device *dev = simple_priv_to_dev(priv); diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index 5df604de4f11937679c628c967de885cbbf7634f..75ae1899452b9b0272a1934a9f1634998f24ab1a 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -1688,6 +1688,7 @@ TRACE_EVENT(qgroup_update_reserve, __entry->qgid = qgroup->qgroupid; __entry->cur_reserved = qgroup->rsv.values[type]; __entry->diff = diff; + __entry->type = type; ), TP_printk_btrfs("qgid=%llu type=%s cur_reserved=%llu diff=%lld", @@ -1710,6 +1711,7 @@ TRACE_EVENT(qgroup_meta_reserve, TP_fast_assign_btrfs(root->fs_info, __entry->refroot = root->root_key.objectid; __entry->diff = diff; + __entry->type = type; ), TP_printk_btrfs("refroot=%llu(%s) type=%s diff=%lld", @@ -1726,7 +1728,6 @@ TRACE_EVENT(qgroup_meta_convert, TP_STRUCT__entry_btrfs( __field( u64, refroot ) __field( s64, diff ) - __field( int, type ) ), TP_fast_assign_btrfs(root->fs_info, diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index edc5c887a44c81864323b86d24e134a0b507e1a8..191fe447f9908c64bafad0ae55724136c75c08ea 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -519,10 +519,10 @@ TRACE_EVENT(rxrpc_local, ); TRACE_EVENT(rxrpc_peer, - TP_PROTO(struct rxrpc_peer *peer, enum rxrpc_peer_trace op, + TP_PROTO(unsigned int peer_debug_id, enum rxrpc_peer_trace op, int usage, const void *where), - TP_ARGS(peer, op, usage, where), + TP_ARGS(peer_debug_id, op, usage, where), TP_STRUCT__entry( __field(unsigned int, peer ) @@ -532,7 +532,7 @@ TRACE_EVENT(rxrpc_peer, ), TP_fast_assign( - __entry->peer = peer->debug_id; + __entry->peer = peer_debug_id; __entry->op = op; __entry->usage = usage; __entry->where = where; @@ -546,10 +546,10 @@ TRACE_EVENT(rxrpc_peer, ); TRACE_EVENT(rxrpc_conn, - TP_PROTO(struct rxrpc_connection *conn, enum rxrpc_conn_trace op, + TP_PROTO(unsigned int conn_debug_id, enum rxrpc_conn_trace op, int usage, const void *where), - TP_ARGS(conn, op, usage, where), + TP_ARGS(conn_debug_id, op, usage, where), TP_STRUCT__entry( __field(unsigned int, conn ) @@ -559,7 +559,7 @@ TRACE_EVENT(rxrpc_conn, ), TP_fast_assign( - __entry->conn = conn->debug_id; + __entry->conn = conn_debug_id; __entry->op = op; __entry->usage = usage; __entry->where = where; @@ -606,10 +606,10 @@ TRACE_EVENT(rxrpc_client, ); TRACE_EVENT(rxrpc_call, - TP_PROTO(struct rxrpc_call *call, enum rxrpc_call_trace op, + TP_PROTO(unsigned int call_debug_id, enum rxrpc_call_trace op, int usage, const void *where, const void *aux), - TP_ARGS(call, op, usage, where, aux), + TP_ARGS(call_debug_id, op, usage, where, aux), TP_STRUCT__entry( __field(unsigned int, call ) @@ -620,7 +620,7 @@ TRACE_EVENT(rxrpc_call, ), TP_fast_assign( - __entry->call = call->debug_id; + __entry->call = call_debug_id; __entry->op = op; __entry->usage = usage; __entry->where = where; diff --git a/include/trace/events/sock.h b/include/trace/events/sock.h index a0c4b8a3096604a9817a0f78f58409123a300352..51fe9f6719eb13d872054676078df87e293fcd01 100644 --- a/include/trace/events/sock.h +++ b/include/trace/events/sock.h @@ -82,7 +82,7 @@ TRACE_EVENT(sock_rcvqueue_full, TP_fast_assign( __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc); __entry->truesize = skb->truesize; - __entry->sk_rcvbuf = sk->sk_rcvbuf; + __entry->sk_rcvbuf = READ_ONCE(sk->sk_rcvbuf); ), TP_printk("rmem_alloc=%d truesize=%u sk_rcvbuf=%d", @@ -115,7 +115,7 @@ TRACE_EVENT(sock_exceed_buf_limit, __entry->rmem_alloc = atomic_read(&sk->sk_rmem_alloc); __entry->sysctl_wmem = sk_get_wmem0(sk, prot); __entry->wmem_alloc = refcount_read(&sk->sk_wmem_alloc); - __entry->wmem_queued = sk->sk_wmem_queued; + __entry->wmem_queued = READ_ONCE(sk->sk_wmem_queued); __entry->kind = kind; ), diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 39ccfe9311c387ba0f6c0f88e605c05b0189e02a..1beb174ad9505634151c5ac2896ae63bcced028e 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -17,7 +17,8 @@ #define FSCRYPT_POLICY_FLAGS_PAD_32 0x03 #define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04 -#define FSCRYPT_POLICY_FLAGS_VALID 0x07 +#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 0x08 +#define FSCRYPT_POLICY_FLAGS_VALID 0x0F /* Encryption algorithms */ #define FSCRYPT_MODE_AES_256_XTS 1 diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 802b0377a49e55b7ecacc523f10efb5622c6f5f6..373cada8981595269d8142fdc5d331ec2902aceb 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -38,6 +38,43 @@ * * Protocol changelog: * + * 7.1: + * - add the following messages: + * FUSE_SETATTR, FUSE_SYMLINK, FUSE_MKNOD, FUSE_MKDIR, FUSE_UNLINK, + * FUSE_RMDIR, FUSE_RENAME, FUSE_LINK, FUSE_OPEN, FUSE_READ, FUSE_WRITE, + * FUSE_RELEASE, FUSE_FSYNC, FUSE_FLUSH, FUSE_SETXATTR, FUSE_GETXATTR, + * FUSE_LISTXATTR, FUSE_REMOVEXATTR, FUSE_OPENDIR, FUSE_READDIR, + * FUSE_RELEASEDIR + * - add padding to messages to accommodate 32-bit servers on 64-bit kernels + * + * 7.2: + * - add FOPEN_DIRECT_IO and FOPEN_KEEP_CACHE flags + * - add FUSE_FSYNCDIR message + * + * 7.3: + * - add FUSE_ACCESS message + * - add FUSE_CREATE message + * - add filehandle to fuse_setattr_in + * + * 7.4: + * - add frsize to fuse_kstatfs + * - clean up request size limit checking + * + * 7.5: + * - add flags and max_write to fuse_init_out + * + * 7.6: + * - add max_readahead to fuse_init_in and fuse_init_out + * + * 7.7: + * - add FUSE_INTERRUPT message + * - add POSIX file lock support + * + * 7.8: + * - add lock_owner and flags fields to fuse_release_in + * - add FUSE_BMAP message + * - add FUSE_DESTROY message + * * 7.9: * - new fuse_getattr_in input argument of GETATTR * - add lk_flags in fuse_lk_in diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 85387c76c24f384ac31a934ca14f0e76faf1ba3a..35125b6c30de56fd3c246a26b3633878d2977f18 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -808,7 +808,10 @@ #define SW_LINEIN_INSERT 0x0d /* set = inserted */ #define SW_MUTE_DEVICE 0x0e /* set = device disabled */ #define SW_PEN_INSERTED 0x0f /* set = pen inserted */ -#define SW_MAX 0x0f +#define SW_HPHL_OVERCURRENT 0x10 /* set = over current on left hph */ +#define SW_HPHR_OVERCURRENT 0x11 /* set = over current on right hph */ +#define SW_UNSUPPORT_INSERT 0x12 /* set = unsupported device inserted */ +#define SW_MAX 0x20 #define SW_CNT (SW_MAX+1) /* diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 530638dffd934128352cd39ef1fa3f1de0c6e444..ebb9755ed9d78900f6c4f6ad201ad4c547044646 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -70,7 +70,7 @@ * Common stuff for both V4L1 and V4L2 * Moved from videodev.h */ -#define VIDEO_MAX_FRAME 32 +#define VIDEO_MAX_FRAME 64 #define VIDEO_MAX_PLANES 8 /* @@ -935,7 +935,9 @@ struct v4l2_requestbuffers { * descriptor associated with this plane * @data_offset: offset in the plane to the start of data; usually 0, * unless there is a header in front of the data - * + * @reserved: few userspace clients and drivers use reserved fields + * and it is up to them how these fields are used. v4l2 + * simply copy reserved fields between them. * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer * with two planes can have one plane for Y, and another for interleaved CbCr * components. Each plane can reside in a separate memory buffer, or even in @@ -950,6 +952,7 @@ struct v4l2_plane { __s32 fd; } m; __u32 data_offset; + /* reserved fields used by few userspace clients and drivers */ __u32 reserved[11]; }; diff --git a/init/Kconfig.gki b/init/Kconfig.gki index b2f3ecefd782c7e203dfe91e0b3da73e1a468a41..c5a080e7784b84c9b03367320e0783b3491f0997 100644 --- a/init/Kconfig.gki +++ b/init/Kconfig.gki @@ -4,6 +4,7 @@ config GKI_HIDDEN_DRM_CONFIGS select DRM_GEM_CMA_HELPER select DRM_KMS_CMA_HELPER select DRM_MIPI_DSI + select SND_PCM_ELD help Dummy config option used to enable hidden DRM configs. These are normally selected implicitely when including a @@ -12,6 +13,7 @@ config GKI_HIDDEN_DRM_CONFIGS config GKI_HIDDEN_REGMAP_CONFIGS bool "Hidden Regmap configs needed for GKI" select REGMAP_IRQ + select REGMAP_MMIO help Dummy config option used to enable hidden regmap configs. These are normally selected implicitely when a module @@ -20,11 +22,20 @@ config GKI_HIDDEN_REGMAP_CONFIGS config GKI_HIDDEN_SND_SOC_CONFIGS bool "Hidden SND_SOC configs needed for GKI" select SND_SOC_GENERIC_DMAENGINE_PCM if (SND_SOC && SND) + select SND_PCM_IEC958 help Dummy config option used to enable hidden SND_SOC configs. These are normally selected implicitely when a module that relies on it is configured. +config GKI_HIDDEN_MMC_CONFIGS + bool "Hidden MMC configs needed for GKI" + select MMC_SDHCI_IO_ACCESSORS if (MMC_SDHCI) + help + Dummy config option used to enable hidden MMC configs. + These are normally selected implicitely when a module + that relies on it is configured. + config GKI_HIDDEN_GPIO_CONFIGS bool "Hidden GPIO configs needed for GKI" select PINCTRL_SINGLE if (PINCTRL && OF && HAS_IOMEM) @@ -34,6 +45,23 @@ config GKI_HIDDEN_GPIO_CONFIGS These are normally selected implicitely when a module that relies on it is configured. +config GKI_HIDDEN_QCOM_CONFIGS + bool "Hidden QCOM configs needed for GKI" + select QCOM_SMEM_STATE + help + Dummy config option used to enable hidden QCOM configs. + These are normally selected implicitely when a module + that relies on it is configured. + +config GKI_HIDDEN_MEDIA_CONFIGS + bool "Hidden Media configs needed for GKI" + select VIDEOBUF2_CORE + select MEDIA_SUPPORT + help + Dummy config option used to enable hidden media configs. + These are normally selected implicitely when a module + that relies on it is configured. + # LEGACY_WEXT_ALLCONFIG Discussed upstream, soundly rejected as a unique # problem for GKI to solve. It should be noted that these extensions are # in-effect deprecated and generally unsupported and we should pressure @@ -65,8 +93,11 @@ config GKI_HACKS_TO_FIX select GKI_HIDDEN_DRM_CONFIGS select GKI_HIDDEN_REGMAP_CONFIGS select GKI_HIDDEN_SND_SOC_CONFIGS + select GKI_HIDDEN_MMC_CONFIGS select GKI_HIDDEN_GPIO_CONFIGS + select GKI_HIDDEN_QCOM_CONFIGS select GKI_LEGACY_WEXT_ALLCONFIG + select GKI_HIDDEN_MEDIA_CONFIGS help Dummy config option used to enable core functionality used by modules that may not be selectable in this config. diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 66088a9e9b9e220b9b823999d4cc9b022e203c5f..ef0e1e3e66f4a50308819a332812fa5e88488afe 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -502,7 +502,7 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt) return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false)); } -void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp) +static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp) { int i; diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index d27f3b60ff6d30a753b7b92b9126629eaab2bf4d..3867864cdc2fbb833cd063f2ee05f754a376b0a6 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -128,7 +128,7 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr) if (!dtab->n_buckets) /* Overflow check */ return -EINVAL; - cost += sizeof(struct hlist_head) * dtab->n_buckets; + cost += (u64) sizeof(struct hlist_head) * dtab->n_buckets; } /* if map size is larger than memlock limit, reject it */ @@ -719,6 +719,32 @@ const struct bpf_map_ops dev_map_hash_ops = { .map_check_btf = map_check_no_btf, }; +static void dev_map_hash_remove_netdev(struct bpf_dtab *dtab, + struct net_device *netdev) +{ + unsigned long flags; + u32 i; + + spin_lock_irqsave(&dtab->index_lock, flags); + for (i = 0; i < dtab->n_buckets; i++) { + struct bpf_dtab_netdev *dev; + struct hlist_head *head; + struct hlist_node *next; + + head = dev_map_index_hash(dtab, i); + + hlist_for_each_entry_safe(dev, next, head, index_hlist) { + if (netdev != dev->dev) + continue; + + dtab->items--; + hlist_del_rcu(&dev->index_hlist); + call_rcu(&dev->rcu, __dev_map_entry_free); + } + } + spin_unlock_irqrestore(&dtab->index_lock, flags); +} + static int dev_map_notification(struct notifier_block *notifier, ulong event, void *ptr) { @@ -735,6 +761,11 @@ static int dev_map_notification(struct notifier_block *notifier, */ rcu_read_lock(); list_for_each_entry_rcu(dtab, &dev_map_list, list) { + if (dtab->map.map_type == BPF_MAP_TYPE_DEVMAP_HASH) { + dev_map_hash_remove_netdev(dtab, netdev); + continue; + } + for (i = 0; i < dtab->map.max_entries; i++) { struct bpf_dtab_netdev *dev, *odev; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 82eabd4e38adda6e95f8113d9a7f9bb61b45ab00..0937719b87e2665219c064b0dc886809a9ef8f50 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1326,24 +1326,32 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu) { struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu); + kvfree(aux->func_info); free_used_maps(aux); bpf_prog_uncharge_memlock(aux->prog); security_bpf_prog_free(aux); bpf_prog_free(aux->prog); } +static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred) +{ + bpf_prog_kallsyms_del_all(prog); + btf_put(prog->aux->btf); + bpf_prog_free_linfo(prog); + + if (deferred) + call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu); + else + __bpf_prog_put_rcu(&prog->aux->rcu); +} + static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock) { if (atomic_dec_and_test(&prog->aux->refcnt)) { perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0); /* bpf_prog_free_id() must be called first */ bpf_prog_free_id(prog, do_idr_lock); - bpf_prog_kallsyms_del_all(prog); - btf_put(prog->aux->btf); - kvfree(prog->aux->func_info); - bpf_prog_free_linfo(prog); - - call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu); + __bpf_prog_put_noref(prog, true); } } @@ -1741,11 +1749,12 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) return err; free_used_maps: - bpf_prog_free_linfo(prog); - kvfree(prog->aux->func_info); - btf_put(prog->aux->btf); - bpf_prog_kallsyms_del_subprogs(prog); - free_used_maps(prog->aux); + /* In case we have subprogs, we need to wait for a grace + * period before we can tear down JIT memory since symbols + * are already exposed under kallsyms. + */ + __bpf_prog_put_noref(prog, prog->aux->func_cnt); + return err; free_prog: bpf_prog_uncharge_memlock(prog); free_prog_sec: diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index c52bc91f882b29e44ea8eb56fd0ba9889c6a86df..c87ee6412b36aa8f088844c42abc2b8aa70d2749 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -798,7 +798,8 @@ static int generate_sched_domains(cpumask_var_t **domains, cpumask_subset(cp->cpus_allowed, top_cpuset.effective_cpus)) continue; - if (is_sched_load_balance(cp)) + if (is_sched_load_balance(cp) && + !cpumask_empty(cp->effective_cpus)) csa[csn++] = cp; /* skip @cp's subtree if not a partition root */ diff --git a/kernel/events/core.c b/kernel/events/core.c index db1cbe0b652d87ca29f0e64a4177630c1c15a3d1..9206cc282c6ca3672ab884bd7451b5e56d411880 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5612,8 +5612,10 @@ static void perf_mmap_close(struct vm_area_struct *vma) perf_pmu_output_stop(event); /* now it's safe to free the pages */ - atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm); - atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm); + if (!rb->aux_mmap_locked) + atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm); + else + atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm); /* this has to be the last one */ rb_free_aux(rb); @@ -6952,7 +6954,7 @@ static void __perf_event_output_stop(struct perf_event *event, void *data) static int __perf_pmu_output_stop(void *info) { struct perf_event *event = info; - struct pmu *pmu = event->pmu; + struct pmu *pmu = event->ctx->pmu; struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); struct remote_output ro = { .rb = event->rb, @@ -10638,7 +10640,7 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr, attr->size = size; - if (attr->__reserved_1) + if (attr->__reserved_1 || attr->__reserved_2) return -EINVAL; if (attr->sample_type & ~(PERF_SAMPLE_MAX-1)) diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 94d38a39d72ecaf3ad0cbee26f5aa9fa1e26fb0e..c74761004ee546272ebbbe56bb2fb62fd4148b0f 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -474,14 +474,17 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, struct vm_area_struct *vma; int ret, is_register, ref_ctr_updated = 0; bool orig_page_huge = false; + unsigned int gup_flags = FOLL_FORCE; is_register = is_swbp_insn(&opcode); uprobe = container_of(auprobe, struct uprobe, arch); retry: + if (is_register) + gup_flags |= FOLL_SPLIT_PMD; /* Read the page with vaddr into memory */ - ret = get_user_pages_remote(NULL, mm, vaddr, 1, - FOLL_FORCE | FOLL_SPLIT_PMD, &old_page, &vma, NULL); + ret = get_user_pages_remote(NULL, mm, vaddr, 1, gup_flags, + &old_page, &vma, NULL); if (ret <= 0) return ret; @@ -489,6 +492,12 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, if (ret <= 0) goto put_old; + if (WARN(!is_register && PageCompound(old_page), + "uprobe unregister should never work on compound page\n")) { + ret = -EINVAL; + goto put_old; + } + /* We are going to replace instruction, update ref_ctr. */ if (!ref_ctr_updated && uprobe->ref_ctr_offset) { ret = update_ref_ctr(uprobe, mm, is_register ? 1 : -1); diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index 9ff449888d9cda491a39b0ffeba27c31d47a72b3..5a0fc0b0403a6c46cd41a0b73a07846eb118a016 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh @@ -71,7 +71,13 @@ done | cpio --quiet -pd $cpio_dir >/dev/null 2>&1 find $cpio_dir -type f -print0 | xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;' -tar -Jcf $tarfile -C $cpio_dir/ . > /dev/null +# Create archive and try to normalize metadata for reproducibility. +# For compatibility with older versions of tar, files are fed to tar +# pre-sorted, as --sort=name might not be available. +find $cpio_dir -printf "./%P\n" | LC_ALL=C sort | \ + tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ + --owner=0 --group=0 --numeric-owner --no-recursion \ + -Jcf $tarfile -C $cpio_dir/ -T - > /dev/null echo "$src_files_md5" > kernel/kheaders.md5 echo "$obj_files_md5" >> kernel/kheaders.md5 diff --git a/kernel/kthread.c b/kernel/kthread.c index 621467c33fefda0e580572cbfa865d7472872f75..b262f47046ca4feb66f61dc802a8a45bd15c222b 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -866,9 +866,9 @@ void kthread_delayed_work_timer_fn(struct timer_list *t) } EXPORT_SYMBOL(kthread_delayed_work_timer_fn); -void __kthread_queue_delayed_work(struct kthread_worker *worker, - struct kthread_delayed_work *dwork, - unsigned long delay) +static void __kthread_queue_delayed_work(struct kthread_worker *worker, + struct kthread_delayed_work *dwork, + unsigned long delay) { struct timer_list *timer = &dwork->timer; struct kthread_work *work = &dwork->work; diff --git a/kernel/power/main.c b/kernel/power/main.c index e8710d179b35beace0e7d48f1a2fd7af93e09ddf..e26de7af520beba281df4e42f11f06b150a0fab7 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "power.h" diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 9568a2fe7c116155f6c6c2c4a3220cd58f78a32b..04e83fdfbe80c016d986adae9fe2fd36bc2ca8d7 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -650,3 +650,243 @@ static int __init pm_qos_power_init(void) } late_initcall(pm_qos_power_init); + +/* Definitions related to the frequency QoS below. */ + +/** + * freq_constraints_init - Initialize frequency QoS constraints. + * @qos: Frequency QoS constraints to initialize. + */ +void freq_constraints_init(struct freq_constraints *qos) +{ + struct pm_qos_constraints *c; + + c = &qos->min_freq; + plist_head_init(&c->list); + c->target_value = FREQ_QOS_MIN_DEFAULT_VALUE; + c->default_value = FREQ_QOS_MIN_DEFAULT_VALUE; + c->no_constraint_value = FREQ_QOS_MIN_DEFAULT_VALUE; + c->type = PM_QOS_MAX; + c->notifiers = &qos->min_freq_notifiers; + BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers); + + c = &qos->max_freq; + plist_head_init(&c->list); + c->target_value = FREQ_QOS_MAX_DEFAULT_VALUE; + c->default_value = FREQ_QOS_MAX_DEFAULT_VALUE; + c->no_constraint_value = FREQ_QOS_MAX_DEFAULT_VALUE; + c->type = PM_QOS_MIN; + c->notifiers = &qos->max_freq_notifiers; + BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers); +} + +/** + * freq_qos_read_value - Get frequency QoS constraint for a given list. + * @qos: Constraints to evaluate. + * @type: QoS request type. + */ +s32 freq_qos_read_value(struct freq_constraints *qos, + enum freq_qos_req_type type) +{ + s32 ret; + + switch (type) { + case FREQ_QOS_MIN: + ret = IS_ERR_OR_NULL(qos) ? + FREQ_QOS_MIN_DEFAULT_VALUE : + pm_qos_read_value(&qos->min_freq); + break; + case FREQ_QOS_MAX: + ret = IS_ERR_OR_NULL(qos) ? + FREQ_QOS_MAX_DEFAULT_VALUE : + pm_qos_read_value(&qos->max_freq); + break; + default: + WARN_ON(1); + ret = 0; + } + + return ret; +} + +/** + * freq_qos_apply - Add/modify/remove frequency QoS request. + * @req: Constraint request to apply. + * @action: Action to perform (add/update/remove). + * @value: Value to assign to the QoS request. + */ +static int freq_qos_apply(struct freq_qos_request *req, + enum pm_qos_req_action action, s32 value) +{ + int ret; + + switch(req->type) { + case FREQ_QOS_MIN: + ret = pm_qos_update_target(&req->qos->min_freq, &req->pnode, + action, value); + break; + case FREQ_QOS_MAX: + ret = pm_qos_update_target(&req->qos->max_freq, &req->pnode, + action, value); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +/** + * freq_qos_add_request - Insert new frequency QoS request into a given list. + * @qos: Constraints to update. + * @req: Preallocated request object. + * @type: Request type. + * @value: Request value. + * + * Insert a new entry into the @qos list of requests, recompute the effective + * QoS constraint value for that list and initialize the @req object. The + * caller needs to save that object for later use in updates and removal. + * + * Return 1 if the effective constraint value has changed, 0 if the effective + * constraint value has not changed, or a negative error code on failures. + */ +int freq_qos_add_request(struct freq_constraints *qos, + struct freq_qos_request *req, + enum freq_qos_req_type type, s32 value) +{ + int ret; + + if (IS_ERR_OR_NULL(qos) || !req) + return -EINVAL; + + if (WARN(freq_qos_request_active(req), + "%s() called for active request\n", __func__)) + return -EINVAL; + + req->qos = qos; + req->type = type; + ret = freq_qos_apply(req, PM_QOS_ADD_REQ, value); + if (ret < 0) { + req->qos = NULL; + req->type = 0; + } + + return ret; +} +EXPORT_SYMBOL_GPL(freq_qos_add_request); + +/** + * freq_qos_update_request - Modify existing frequency QoS request. + * @req: Request to modify. + * @new_value: New request value. + * + * Update an existing frequency QoS request along with the effective constraint + * value for the list of requests it belongs to. + * + * Return 1 if the effective constraint value has changed, 0 if the effective + * constraint value has not changed, or a negative error code on failures. + */ +int freq_qos_update_request(struct freq_qos_request *req, s32 new_value) +{ + if (!req) + return -EINVAL; + + if (WARN(!freq_qos_request_active(req), + "%s() called for unknown object\n", __func__)) + return -EINVAL; + + if (req->pnode.prio == new_value) + return 0; + + return freq_qos_apply(req, PM_QOS_UPDATE_REQ, new_value); +} +EXPORT_SYMBOL_GPL(freq_qos_update_request); + +/** + * freq_qos_remove_request - Remove frequency QoS request from its list. + * @req: Request to remove. + * + * Remove the given frequency QoS request from the list of constraints it + * belongs to and recompute the effective constraint value for that list. + * + * Return 1 if the effective constraint value has changed, 0 if the effective + * constraint value has not changed, or a negative error code on failures. + */ +int freq_qos_remove_request(struct freq_qos_request *req) +{ + if (!req) + return -EINVAL; + + if (WARN(!freq_qos_request_active(req), + "%s() called for unknown object\n", __func__)) + return -EINVAL; + + return freq_qos_apply(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); +} +EXPORT_SYMBOL_GPL(freq_qos_remove_request); + +/** + * freq_qos_add_notifier - Add frequency QoS change notifier. + * @qos: List of requests to add the notifier to. + * @type: Request type. + * @notifier: Notifier block to add. + */ +int freq_qos_add_notifier(struct freq_constraints *qos, + enum freq_qos_req_type type, + struct notifier_block *notifier) +{ + int ret; + + if (IS_ERR_OR_NULL(qos) || !notifier) + return -EINVAL; + + switch (type) { + case FREQ_QOS_MIN: + ret = blocking_notifier_chain_register(qos->min_freq.notifiers, + notifier); + break; + case FREQ_QOS_MAX: + ret = blocking_notifier_chain_register(qos->max_freq.notifiers, + notifier); + break; + default: + WARN_ON(1); + ret = -EINVAL; + } + + return ret; +} +EXPORT_SYMBOL_GPL(freq_qos_add_notifier); + +/** + * freq_qos_remove_notifier - Remove frequency QoS change notifier. + * @qos: List of requests to remove the notifier from. + * @type: Request type. + * @notifier: Notifier block to remove. + */ +int freq_qos_remove_notifier(struct freq_constraints *qos, + enum freq_qos_req_type type, + struct notifier_block *notifier) +{ + int ret; + + if (IS_ERR_OR_NULL(qos) || !notifier) + return -EINVAL; + + switch (type) { + case FREQ_QOS_MIN: + ret = blocking_notifier_chain_unregister(qos->min_freq.notifiers, + notifier); + break; + case FREQ_QOS_MAX: + ret = blocking_notifier_chain_unregister(qos->max_freq.notifiers, + notifier); + break; + default: + WARN_ON(1); + ret = -EINVAL; + } + + return ret; +} +EXPORT_SYMBOL_GPL(freq_qos_remove_notifier); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index c05d05094e70d33153267cd3818b6b2bbc9ddb4b..eb3a7b8bd3cb2a768cdb5e93e783599591537f29 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3919,7 +3919,7 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) p = fair_sched_class.pick_next_task(rq, prev, rf); if (unlikely(p == RETRY_TASK)) - goto restart; + goto again; /* Assumes fair_sched_class->next == idle_sched_class */ if (unlikely(!p)) @@ -3928,19 +3928,14 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) return p; } -restart: - /* - * Ensure that we put DL/RT tasks before the pick loop, such that they - * can PULL higher prio tasks when we lower the RQ 'priority'. - */ - prev->sched_class->put_prev_task(rq, prev, rf); - if (!rq->nr_running) - newidle_balance(rq, rf); - +again: for_each_class(class) { - p = class->pick_next_task(rq, NULL, NULL); - if (p) + p = class->pick_next_task(rq, prev, rf); + if (p) { + if (unlikely(p == RETRY_TASK)) + goto again; return p; + } } /* The idle class should always have a runnable task: */ diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 2dc48720f18914a9f828f5cd653b751a045c4556..4ed2d10c196c5ca8e4ff27d1bd144730e5e79693 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1761,13 +1761,39 @@ pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) struct task_struct *p; struct dl_rq *dl_rq; - WARN_ON_ONCE(prev || rf); - dl_rq = &rq->dl; + if (need_pull_dl_task(rq, prev)) { + /* + * This is OK, because current is on_cpu, which avoids it being + * picked for load-balance and preemption/IRQs are still + * disabled avoiding further scheduler activity on it and we're + * being very careful to re-start the picking loop. + */ + rq_unpin_lock(rq, rf); + pull_dl_task(rq); + rq_repin_lock(rq, rf); + /* + * pull_dl_task() can drop (and re-acquire) rq->lock; this + * means a stop task can slip in, in which case we need to + * re-start task selection. + */ + if (rq->stop && task_on_rq_queued(rq->stop)) + return RETRY_TASK; + } + + /* + * When prev is DL, we may throttle it in put_prev_task(). + * So, we update time before we check for dl_nr_running. + */ + if (prev->sched_class == &dl_sched_class) + update_curr_dl(rq); + if (unlikely(!dl_rq->dl_nr_running)) return NULL; + put_prev_task(rq, prev); + dl_se = pick_next_dl_entity(rq, dl_rq); BUG_ON(!dl_se); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 8f8692baa6790134aa0e8edee7c0efeacb50f805..31b3e1a10bb36ed8dfe01d15ec65ea14c471eda5 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6810,7 +6810,7 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf goto idle; #ifdef CONFIG_FAIR_GROUP_SCHED - if (!prev || prev->sched_class != &fair_sched_class) + if (prev->sched_class != &fair_sched_class) goto simple; /* @@ -6887,8 +6887,8 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf goto done; simple: #endif - if (prev) - put_prev_task(rq, prev); + + put_prev_task(rq, prev); do { se = pick_next_entity(cfs_rq, NULL); @@ -6916,9 +6916,6 @@ done: __maybe_unused; return p; idle: - if (!rf) - return NULL; - new_tasks = newidle_balance(rq, rf); /* diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 8dad5aa600eacbff82480ef84eae684308e6da54..e397a165b40829a3feeb4ae79e1eb7287e079c8c 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -390,9 +390,7 @@ pick_next_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf { struct task_struct *next = rq->idle; - if (prev) - put_prev_task(rq, prev); - + put_prev_task(rq, prev); set_next_task_idle(rq, next); return next; diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index ebaa4e619684112cc6c19bc6ba69fe15c3f2b52a..f65653b139bc347ea344cd300d8d97995a200c06 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1554,11 +1554,38 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) struct task_struct *p; struct rt_rq *rt_rq = &rq->rt; - WARN_ON_ONCE(prev || rf); + if (need_pull_rt_task(rq, prev)) { + /* + * This is OK, because current is on_cpu, which avoids it being + * picked for load-balance and preemption/IRQs are still + * disabled avoiding further scheduler activity on it and we're + * being very careful to re-start the picking loop. + */ + rq_unpin_lock(rq, rf); + pull_rt_task(rq); + rq_repin_lock(rq, rf); + /* + * pull_rt_task() can drop (and re-acquire) rq->lock; this + * means a dl or stop task can slip in, in which case we need + * to re-start task selection. + */ + if (unlikely((rq->stop && task_on_rq_queued(rq->stop)) || + rq->dl.dl_nr_running)) + return RETRY_TASK; + } + + /* + * We may dequeue prev's rt_rq in put_prev_task(). + * So, we update time before rt_queued check. + */ + if (prev->sched_class == &rt_sched_class) + update_curr_rt(rq); if (!rt_rq->rt_queued) return NULL; + put_prev_task(rq, prev); + p = _pick_next_task_rt(rq); set_next_task_rt(rq, p); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 4f0d1668c283b89555057d6b14b6158a19baaf7d..e14ae174e0d1df8144ce6edd5a800d51a6e94e3d 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1724,15 +1724,12 @@ struct sched_class { void (*check_preempt_curr)(struct rq *rq, struct task_struct *p, int flags); /* - * Both @prev and @rf are optional and may be NULL, in which case the - * caller must already have invoked put_prev_task(rq, prev, rf). + * It is the responsibility of the pick_next_task() method that will + * return the next task to call put_prev_task() on the @prev task or + * something equivalent. * - * Otherwise it is the responsibility of the pick_next_task() to call - * put_prev_task() on the @prev task or something equivalent, IFF it - * returns a next task. - * - * In that case (@rf != NULL) it may return RETRY_TASK when it finds a - * higher prio class has runnable tasks. + * May return RETRY_TASK when it finds a higher prio class has runnable + * tasks. */ struct task_struct * (*pick_next_task)(struct rq *rq, struct task_struct *prev, diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 7e1cee4e65b211ece98bd640bf691a29de329ed1..8f414018d5e0ef3ecc5095f347fa1a18a25df593 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -33,11 +33,10 @@ pick_next_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf { struct task_struct *stop = rq->stop; - WARN_ON_ONCE(prev || rf); - if (!stop || !task_on_rq_queued(stop)) return NULL; + put_prev_task(rq, prev); set_next_task_stop(rq, stop); return stop; diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 4ad1e5194555808debecc58344e336e9fe054c9f..4a6a2c0f60c897dd8e2568db0cf374a53737e83f 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -1951,13 +1951,16 @@ static struct sched_domain_topology_level static int build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *attr) { - enum s_alloc alloc_state; + enum s_alloc alloc_state = sa_none; struct sched_domain *sd; struct s_data d; int i, ret = -ENOMEM; struct sched_domain_topology_level *tl_asym; bool has_asym = false; + if (WARN_ON(cpumask_empty(cpu_map))) + goto error; + alloc_state = __visit_domain_allocation_hell(&d, cpu_map); if (alloc_state != sa_rootdomain) goto error; @@ -2022,7 +2025,7 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att rcu_read_unlock(); if (has_asym) - static_branch_enable_cpuslocked(&sched_asym_cpucapacity); + static_branch_inc_cpuslocked(&sched_asym_cpucapacity); ret = 0; error: @@ -2112,8 +2115,12 @@ int sched_init_domains(const struct cpumask *cpu_map) */ static void detach_destroy_domains(const struct cpumask *cpu_map) { + unsigned int cpu = cpumask_any(cpu_map); int i; + if (rcu_access_pointer(per_cpu(sd_asym_cpucapacity, cpu))) + static_branch_dec_cpuslocked(&sched_asym_cpucapacity); + rcu_read_lock(); for_each_cpu(i, cpu_map) cpu_attach_domain(NULL, &def_root_domain, i); diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index c7031a22aa7bcb9dfd0f73da764108a321e99442..998d50ee2d9bbb0856a1a374279dfb170db751a2 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -7,6 +7,7 @@ * Copyright (C) 2010 SUSE Linux Products GmbH * Copyright (C) 2010 Tejun Heo */ +#include #include #include #include @@ -167,7 +168,7 @@ static void set_state(struct multi_stop_data *msdata, /* Reset ack counter. */ atomic_set(&msdata->thread_ack, msdata->num_threads); smp_wmb(); - msdata->state = newstate; + WRITE_ONCE(msdata->state, newstate); } /* Last one to ack a state moves to the next state. */ @@ -186,7 +187,7 @@ void __weak stop_machine_yield(const struct cpumask *cpumask) static int multi_cpu_stop(void *data) { struct multi_stop_data *msdata = data; - enum multi_stop_state curstate = MULTI_STOP_NONE; + enum multi_stop_state newstate, curstate = MULTI_STOP_NONE; int cpu = smp_processor_id(), err = 0; const struct cpumask *cpumask; unsigned long flags; @@ -210,8 +211,9 @@ static int multi_cpu_stop(void *data) do { /* Chill out and ensure we re-read multi_stop_state. */ stop_machine_yield(cpumask); - if (msdata->state != curstate) { - curstate = msdata->state; + newstate = READ_ONCE(msdata->state); + if (newstate != curstate) { + curstate = newstate; switch (curstate) { case MULTI_STOP_DISABLE_IRQ: local_irq_disable(); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 570cf60837128d8fb741e05d1200f2d095fa43d3..f5ee2d6dc1c163d23b2396e61d97347adb8e63b2 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -164,7 +164,7 @@ static unsigned long hung_task_timeout_max = (LONG_MAX/HZ); #ifdef CONFIG_SPARC #endif -#ifdef __hppa__ +#ifdef CONFIG_PARISC extern int pwrsw_enabled; #endif @@ -621,7 +621,7 @@ static struct ctl_table kern_table[] = { .proc_handler = proc_dointvec, }, #endif -#ifdef __hppa__ +#ifdef CONFIG_PARISC { .procname = "soft-power", .data = &pwrsw_enabled, diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 0d4dc241c0fb498036c91a571e65cb00f5d19ba6..65605530ee349c9682690c4fccb43aa9284d4287 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -164,7 +164,7 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer, struct hrtimer_clock_base *base; for (;;) { - base = timer->base; + base = READ_ONCE(timer->base); if (likely(base != &migration_base)) { raw_spin_lock_irqsave(&base->cpu_base->lock, *flags); if (likely(base == timer->base)) @@ -244,7 +244,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base, return base; /* See the comment in lock_hrtimer_base() */ - timer->base = &migration_base; + WRITE_ONCE(timer->base, &migration_base); raw_spin_unlock(&base->cpu_base->lock); raw_spin_lock(&new_base->cpu_base->lock); @@ -253,10 +253,10 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base, raw_spin_unlock(&new_base->cpu_base->lock); raw_spin_lock(&base->cpu_base->lock); new_cpu_base = this_cpu_base; - timer->base = base; + WRITE_ONCE(timer->base, base); goto again; } - timer->base = new_base; + WRITE_ONCE(timer->base, new_base); } else { if (new_cpu_base != this_cpu_base && hrtimer_check_target(timer, new_base)) { diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 92a431981b1c46862da651201f3721140d76af09..42d512fcfda2e6de092831f97bfc75c85b0b6137 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -266,7 +266,7 @@ static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic, /** * thread_group_sample_cputime - Sample cputime for a given task * @tsk: Task for which cputime needs to be started - * @iimes: Storage for time samples + * @samples: Storage for time samples * * Called from sys_getitimer() to calculate the expiry time of an active * timer. That means group cputime accounting is already active. Called @@ -1038,12 +1038,12 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer) * member of @pct->bases[CLK].nextevt. False otherwise */ static inline bool -task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct) +task_cputimers_expired(const u64 *samples, struct posix_cputimers *pct) { int i; for (i = 0; i < CPUCLOCK_MAX; i++) { - if (sample[i] >= pct->bases[i].nextevt) + if (samples[i] >= pct->bases[i].nextevt) return true; } return false; diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index 142b07619918b13db03d1c3a91437c1f96ff28bf..dbd69052eaa6666854b47562c278336a87a14d89 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c @@ -17,6 +17,8 @@ #include #include +#include "timekeeping.h" + /** * struct clock_read_data - data required to read from sched_clock() * diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 0892e38ed6fbeca73258ce357d678c922e48468d..a9dfa04ffa4499117833495aded1db5fdc19eedd 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -272,9 +272,11 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe) goto out; } + mutex_lock(&event_mutex); ret = perf_trace_event_init(tp_event, p_event); if (ret) destroy_local_trace_kprobe(tp_event); + mutex_unlock(&event_mutex); out: kfree(func); return ret; @@ -282,8 +284,10 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe) void perf_kprobe_destroy(struct perf_event *p_event) { + mutex_lock(&event_mutex); perf_trace_event_close(p_event); perf_trace_event_unreg(p_event); + mutex_unlock(&event_mutex); destroy_local_trace_kprobe(p_event->tp_event); } diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 57648c5aa6797767781f3d9464eed32f426c1b40..7482a1466ebfede5ce50e458d5b80cc2c6a18951 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -679,6 +679,8 @@ static bool synth_field_signed(char *type) { if (str_has_prefix(type, "u")) return false; + if (strcmp(type, "gfp_t") == 0) + return false; return true; } diff --git a/lib/generic-radix-tree.c b/lib/generic-radix-tree.c index ae25e2fa2187bc0ec9a90691c008fe4b53a3c0cf..f25eb111c0516f0191477662a1a88211caca053e 100644 --- a/lib/generic-radix-tree.c +++ b/lib/generic-radix-tree.c @@ -2,6 +2,7 @@ #include #include #include +#include #define GENRADIX_ARY (PAGE_SIZE / sizeof(struct genradix_node *)) #define GENRADIX_ARY_SHIFT ilog2(GENRADIX_ARY) @@ -75,6 +76,27 @@ void *__genradix_ptr(struct __genradix *radix, size_t offset) } EXPORT_SYMBOL(__genradix_ptr); +static inline struct genradix_node *genradix_alloc_node(gfp_t gfp_mask) +{ + struct genradix_node *node; + + node = (struct genradix_node *)__get_free_page(gfp_mask|__GFP_ZERO); + + /* + * We're using pages (not slab allocations) directly for kernel data + * structures, so we need to explicitly inform kmemleak of them in order + * to avoid false positive memory leak reports. + */ + kmemleak_alloc(node, PAGE_SIZE, 1, gfp_mask); + return node; +} + +static inline void genradix_free_node(struct genradix_node *node) +{ + kmemleak_free(node); + free_page((unsigned long)node); +} + /* * Returns pointer to the specified byte @offset within @radix, allocating it if * necessary - newly allocated slots are always zeroed out: @@ -97,8 +119,7 @@ void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset, break; if (!new_node) { - new_node = (void *) - __get_free_page(gfp_mask|__GFP_ZERO); + new_node = genradix_alloc_node(gfp_mask); if (!new_node) return NULL; } @@ -121,8 +142,7 @@ void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset, n = READ_ONCE(*p); if (!n) { if (!new_node) { - new_node = (void *) - __get_free_page(gfp_mask|__GFP_ZERO); + new_node = genradix_alloc_node(gfp_mask); if (!new_node) return NULL; } @@ -133,7 +153,7 @@ void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset, } if (new_node) - free_page((unsigned long) new_node); + genradix_free_node(new_node); return &n->data[offset]; } @@ -191,7 +211,7 @@ static void genradix_free_recurse(struct genradix_node *n, unsigned level) genradix_free_recurse(n->children[i], level - 1); } - free_page((unsigned long) n); + genradix_free_node(n); } int __genradix_prealloc(struct __genradix *radix, size_t size, diff --git a/lib/test_meminit.c b/lib/test_meminit.c index 9729f271d15041ac1930eb85922b81ba094a574f..9742e5cb853aa18313d533b17f73d85dc17d50e5 100644 --- a/lib/test_meminit.c +++ b/lib/test_meminit.c @@ -297,6 +297,32 @@ static int __init do_kmem_cache_rcu_persistent(int size, int *total_failures) return 1; } +static int __init do_kmem_cache_size_bulk(int size, int *total_failures) +{ + struct kmem_cache *c; + int i, iter, maxiter = 1024; + int num, bytes; + bool fail = false; + void *objects[10]; + + c = kmem_cache_create("test_cache", size, size, 0, NULL); + for (iter = 0; (iter < maxiter) && !fail; iter++) { + num = kmem_cache_alloc_bulk(c, GFP_KERNEL, ARRAY_SIZE(objects), + objects); + for (i = 0; i < num; i++) { + bytes = count_nonzero_bytes(objects[i], size); + if (bytes) + fail = true; + fill_with_garbage(objects[i], size); + } + + if (num) + kmem_cache_free_bulk(c, num, objects); + } + *total_failures += fail; + return 1; +} + /* * Test kmem_cache allocation by creating caches of different sizes, with and * without constructors, with and without SLAB_TYPESAFE_BY_RCU. @@ -318,6 +344,7 @@ static int __init test_kmemcache(int *total_failures) num_tests += do_kmem_cache_size(size, ctor, rcu, zero, &failures); } + num_tests += do_kmem_cache_size_bulk(size, &failures); } REPORT_FAILURES_IN_FN(); *total_failures += failures; diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c index e365ace06538362abf41fce70273fcb32a2d1f18..5ff04d8fe9716354bb2d2f60117a65dc8481c880 100644 --- a/lib/test_user_copy.c +++ b/lib/test_user_copy.c @@ -47,18 +47,35 @@ static bool is_zeroed(void *from, size_t size) static int test_check_nonzero_user(char *kmem, char __user *umem, size_t size) { int ret = 0; - size_t start, end, i; - size_t zero_start = size / 4; - size_t zero_end = size - zero_start; + size_t start, end, i, zero_start, zero_end; + + if (test(size < 2 * PAGE_SIZE, "buffer too small")) + return -EINVAL; + + /* + * We want to cross a page boundary to exercise the code more + * effectively. We also don't want to make the size we scan too large, + * otherwise the test can take a long time and cause soft lockups. So + * scan a 1024 byte region across the page boundary. + */ + size = 1024; + start = PAGE_SIZE - (size / 2); + + kmem += start; + umem += start; + + zero_start = size / 4; + zero_end = size - zero_start; /* - * We conduct a series of check_nonzero_user() tests on a block of memory - * with the following byte-pattern (trying every possible [start,end] - * pair): + * We conduct a series of check_nonzero_user() tests on a block of + * memory with the following byte-pattern (trying every possible + * [start,end] pair): * * [ 00 ff 00 ff ... 00 00 00 00 ... ff 00 ff 00 ] * - * And we verify that check_nonzero_user() acts identically to memchr_inv(). + * And we verify that check_nonzero_user() acts identically to + * memchr_inv(). */ memset(kmem, 0x0, size); @@ -93,11 +110,13 @@ static int test_copy_struct_from_user(char *kmem, char __user *umem, size_t ksize, usize; umem_src = kmalloc(size, GFP_KERNEL); - if ((ret |= test(umem_src == NULL, "kmalloc failed"))) + ret = test(umem_src == NULL, "kmalloc failed"); + if (ret) goto out_free; expected = kmalloc(size, GFP_KERNEL); - if ((ret |= test(expected == NULL, "kmalloc failed"))) + ret = test(expected == NULL, "kmalloc failed"); + if (ret) goto out_free; /* Fill umem with a fixed byte pattern. */ diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c index e630e7ff57f1f9102e28820ef98f9c49e23da2ed..45f57fd2db649999741f4c2b9d375635453b53db 100644 --- a/lib/vdso/gettimeofday.c +++ b/lib/vdso/gettimeofday.c @@ -214,9 +214,10 @@ int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res) return -1; } - res->tv_sec = 0; - res->tv_nsec = ns; - + if (likely(res)) { + res->tv_sec = 0; + res->tv_nsec = ns; + } return 0; } @@ -245,7 +246,7 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res) ret = clock_getres_fallback(clock, &ts); #endif - if (likely(!ret)) { + if (likely(!ret && res)) { res->tv_sec = ts.tv_sec; res->tv_nsec = ts.tv_nsec; } diff --git a/mm/compaction.c b/mm/compaction.c index ce08b39d85d40f50011111b5ec0621f253ac30a8..672d3c78c6abfcfa152b95113701982fac8221e2 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -270,14 +270,15 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, /* Ensure the start of the pageblock or zone is online and valid */ block_pfn = pageblock_start_pfn(pfn); - block_page = pfn_to_online_page(max(block_pfn, zone->zone_start_pfn)); + block_pfn = max(block_pfn, zone->zone_start_pfn); + block_page = pfn_to_online_page(block_pfn); if (block_page) { page = block_page; pfn = block_pfn; } /* Ensure the end of the pageblock or zone is online and valid */ - block_pfn += pageblock_nr_pages; + block_pfn = pageblock_end_pfn(pfn) - 1; block_pfn = min(block_pfn, zone_end_pfn(zone) - 1); end_page = pfn_to_online_page(block_pfn); if (!end_page) @@ -303,7 +304,7 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, page += (1 << PAGE_ALLOC_COSTLY_ORDER); pfn += (1 << PAGE_ALLOC_COSTLY_ORDER); - } while (page < end_page); + } while (page <= end_page); return false; } diff --git a/mm/filemap.c b/mm/filemap.c index 1146fcfa321511b61e5dd258c9825b6bf759426e..85b7d087eb45a769fd88cbbd15d3647f7702baf7 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "internal.h" #define CREATE_TRACE_POINTS diff --git a/mm/gup.c b/mm/gup.c index 23a9f9c9d377543f9ad28d8e935a896ecbb95caa..8f236a335ae9d25a81665f282f7ef9ccba7802dc 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1973,7 +1973,8 @@ static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end, } static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, - unsigned long end, int write, struct page **pages, int *nr) + unsigned long end, unsigned int flags, + struct page **pages, int *nr) { unsigned long pte_end; struct page *head, *page; @@ -1986,7 +1987,7 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, pte = READ_ONCE(*ptep); - if (!pte_access_permitted(pte, write)) + if (!pte_access_permitted(pte, flags & FOLL_WRITE)) return 0; /* hugepages are never "special" */ @@ -2023,7 +2024,7 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, } static int gup_huge_pd(hugepd_t hugepd, unsigned long addr, - unsigned int pdshift, unsigned long end, int write, + unsigned int pdshift, unsigned long end, unsigned int flags, struct page **pages, int *nr) { pte_t *ptep; @@ -2033,7 +2034,7 @@ static int gup_huge_pd(hugepd_t hugepd, unsigned long addr, ptep = hugepte_offset(hugepd, addr, pdshift); do { next = hugepte_addr_end(addr, end, sz); - if (!gup_hugepte(ptep, sz, addr, end, write, pages, nr)) + if (!gup_hugepte(ptep, sz, addr, end, flags, pages, nr)) return 0; } while (ptep++, addr = next, addr != end); @@ -2041,7 +2042,7 @@ static int gup_huge_pd(hugepd_t hugepd, unsigned long addr, } #else static inline int gup_huge_pd(hugepd_t hugepd, unsigned long addr, - unsigned pdshift, unsigned long end, int write, + unsigned int pdshift, unsigned long end, unsigned int flags, struct page **pages, int *nr) { return 0; @@ -2049,7 +2050,8 @@ static inline int gup_huge_pd(hugepd_t hugepd, unsigned long addr, #endif /* CONFIG_ARCH_HAS_HUGEPD */ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, - unsigned long end, unsigned int flags, struct page **pages, int *nr) + unsigned long end, unsigned int flags, + struct page **pages, int *nr) { struct page *head, *page; int refs; diff --git a/mm/huge_memory.c b/mm/huge_memory.c index c5cb6dcd6c69664c4e9c71d02c20ecae53362e9b..13cc93785006fa03289b8b7318e9e3bf1fd7b056 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2789,8 +2789,13 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) ds_queue->split_queue_len--; list_del(page_deferred_list(head)); } - if (mapping) - __dec_node_page_state(page, NR_SHMEM_THPS); + if (mapping) { + if (PageSwapBacked(page)) + __dec_node_page_state(page, NR_SHMEM_THPS); + else + __dec_node_page_state(page, NR_FILE_THPS); + } + spin_unlock(&ds_queue->split_queue_lock); __split_huge_page(page, list, end, flags); if (PageSwapCache(head)) { diff --git a/mm/hugetlb.c b/mm/hugetlb.c index ef37c85423a5209c528dbbb3e08f48a8bfcb5009..b45a95363a844a12f54eb904437f3fd562057b50 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1084,11 +1084,10 @@ static bool pfn_range_valid_gigantic(struct zone *z, struct page *page; for (i = start_pfn; i < end_pfn; i++) { - if (!pfn_valid(i)) + page = pfn_to_online_page(i); + if (!page) return false; - page = pfn_to_page(i); - if (page_zone(page) != z) return false; diff --git a/mm/init-mm.c b/mm/init-mm.c index fb1e15028ef06b6ff5b68a125df7e434d52787b8..19603302a77ffa9745861183d1afeacd547e0730 100644 --- a/mm/init-mm.c +++ b/mm/init-mm.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 03a8d84badada040c3b8e16200e244ef9ba10094..244607663363141d170f50e0b736d9fdc20c712c 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -526,6 +526,16 @@ static struct kmemleak_object *find_and_get_object(unsigned long ptr, int alias) return object; } +/* + * Remove an object from the object_tree_root and object_list. Must be called + * with the kmemleak_lock held _if_ kmemleak is still enabled. + */ +static void __remove_object(struct kmemleak_object *object) +{ + rb_erase(&object->rb_node, &object_tree_root); + list_del_rcu(&object->object_list); +} + /* * Look up an object in the object search tree and remove it from both * object_tree_root and object_list. The returned object's use_count should be @@ -538,10 +548,8 @@ static struct kmemleak_object *find_and_remove_object(unsigned long ptr, int ali write_lock_irqsave(&kmemleak_lock, flags); object = lookup_object(ptr, alias); - if (object) { - rb_erase(&object->rb_node, &object_tree_root); - list_del_rcu(&object->object_list); - } + if (object) + __remove_object(object); write_unlock_irqrestore(&kmemleak_lock, flags); return object; @@ -1834,12 +1842,16 @@ static const struct file_operations kmemleak_fops = { static void __kmemleak_do_cleanup(void) { - struct kmemleak_object *object; + struct kmemleak_object *object, *tmp; - rcu_read_lock(); - list_for_each_entry_rcu(object, &object_list, object_list) - delete_object_full(object->pointer); - rcu_read_unlock(); + /* + * Kmemleak has already been disabled, no need for RCU list traversal + * or kmemleak_lock held. + */ + list_for_each_entry_safe(object, tmp, &object_list, object_list) { + __remove_object(object); + __delete_object(object); + } } /* diff --git a/mm/memblock.c b/mm/memblock.c index 7d4f61ae666a61123bea4b59b9b02f90ba401f3a..c4b16cae2bc9bdfec99120b14478a4c46ae94627 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1356,9 +1356,6 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, align = SMP_CACHE_BYTES; } - if (end > memblock.current_limit) - end = memblock.current_limit; - again: found = memblock_find_in_range_node(size, align, start, end, nid, flags); @@ -1469,6 +1466,9 @@ static void * __init memblock_alloc_internal( if (WARN_ON_ONCE(slab_is_available())) return kzalloc_node(size, GFP_NOWAIT, nid); + if (max_addr > memblock.current_limit) + max_addr = memblock.current_limit; + alloc = memblock_alloc_range_nid(size, align, min_addr, max_addr, nid); /* retry allocation without lower limit */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index bdac56009a38c0c84cd36bbf1bd474537af76a17..363106578876152b06ced3999cdacefaac0aa485 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5420,6 +5420,8 @@ static int mem_cgroup_move_account(struct page *page, struct mem_cgroup *from, struct mem_cgroup *to) { + struct lruvec *from_vec, *to_vec; + struct pglist_data *pgdat; unsigned long flags; unsigned int nr_pages = compound ? hpage_nr_pages(page) : 1; int ret; @@ -5443,11 +5445,15 @@ static int mem_cgroup_move_account(struct page *page, anon = PageAnon(page); + pgdat = page_pgdat(page); + from_vec = mem_cgroup_lruvec(pgdat, from); + to_vec = mem_cgroup_lruvec(pgdat, to); + spin_lock_irqsave(&from->move_lock, flags); if (!anon && page_mapped(page)) { - __mod_memcg_state(from, NR_FILE_MAPPED, -nr_pages); - __mod_memcg_state(to, NR_FILE_MAPPED, nr_pages); + __mod_lruvec_state(from_vec, NR_FILE_MAPPED, -nr_pages); + __mod_lruvec_state(to_vec, NR_FILE_MAPPED, nr_pages); } /* @@ -5459,14 +5465,14 @@ static int mem_cgroup_move_account(struct page *page, struct address_space *mapping = page_mapping(page); if (mapping_cap_account_dirty(mapping)) { - __mod_memcg_state(from, NR_FILE_DIRTY, -nr_pages); - __mod_memcg_state(to, NR_FILE_DIRTY, nr_pages); + __mod_lruvec_state(from_vec, NR_FILE_DIRTY, -nr_pages); + __mod_lruvec_state(to_vec, NR_FILE_DIRTY, nr_pages); } } if (PageWriteback(page)) { - __mod_memcg_state(from, NR_WRITEBACK, -nr_pages); - __mod_memcg_state(to, NR_WRITEBACK, nr_pages); + __mod_lruvec_state(from_vec, NR_WRITEBACK, -nr_pages); + __mod_lruvec_state(to_vec, NR_WRITEBACK, nr_pages); } #ifdef CONFIG_TRANSPARENT_HUGEPAGE diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 7ef849da8278c1ce659f4930c5df17fbe7e2f7d5..3151c87dff73e68feceb37225a99db991e7a5130 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -199,7 +199,6 @@ struct to_kill { struct task_struct *tsk; unsigned long addr; short size_shift; - char addr_valid; }; /* @@ -324,22 +323,27 @@ static void add_to_kill(struct task_struct *tsk, struct page *p, } } tk->addr = page_address_in_vma(p, vma); - tk->addr_valid = 1; if (is_zone_device_page(p)) tk->size_shift = dev_pagemap_mapping_shift(p, vma); else tk->size_shift = compound_order(compound_head(p)) + PAGE_SHIFT; /* - * In theory we don't have to kill when the page was - * munmaped. But it could be also a mremap. Since that's - * likely very rare kill anyways just out of paranoia, but use - * a SIGKILL because the error is not contained anymore. + * Send SIGKILL if "tk->addr == -EFAULT". Also, as + * "tk->size_shift" is always non-zero for !is_zone_device_page(), + * so "tk->size_shift == 0" effectively checks no mapping on + * ZONE_DEVICE. Indeed, when a devdax page is mmapped N times + * to a process' address space, it's possible not all N VMAs + * contain mappings for the page, but at least one VMA does. + * Only deliver SIGBUS with payload derived from the VMA that + * has a mapping for the page. */ - if (tk->addr == -EFAULT || tk->size_shift == 0) { + if (tk->addr == -EFAULT) { pr_info("Memory failure: Unable to find user space address %lx in %s\n", page_to_pfn(p), tsk->comm); - tk->addr_valid = 0; + } else if (tk->size_shift == 0) { + kfree(tk); + return; } get_task_struct(tsk); tk->tsk = tsk; @@ -366,7 +370,7 @@ static void kill_procs(struct list_head *to_kill, int forcekill, bool fail, * make sure the process doesn't catch the * signal and then access the memory. Just kill it. */ - if (fail || tk->addr_valid == 0) { + if (fail || tk->addr == -EFAULT) { pr_err("Memory failure: %#lx: forcibly killing %s:%d because of failure to unmap corrupted page\n", pfn, tk->tsk->comm, tk->tsk->pid); do_send_sig_info(SIGKILL, SEND_SIG_PRIV, @@ -1253,17 +1257,19 @@ int memory_failure(unsigned long pfn, int flags) if (!sysctl_memory_failure_recovery) panic("Memory failure on page %lx", pfn); - if (!pfn_valid(pfn)) { + p = pfn_to_online_page(pfn); + if (!p) { + if (pfn_valid(pfn)) { + pgmap = get_dev_pagemap(pfn, NULL); + if (pgmap) + return memory_failure_dev_pagemap(pfn, flags, + pgmap); + } pr_err("Memory failure: %#lx: memory outside kernel control\n", pfn); return -ENXIO; } - pgmap = get_dev_pagemap(pfn, NULL); - if (pgmap) - return memory_failure_dev_pagemap(pfn, flags, pgmap); - - p = pfn_to_page(pfn); if (PageHuge(p)) return memory_failure_hugetlb(pfn, flags); if (TestSetPageHWPoison(p)) { diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index b1be791f772dc0fae4d0eef4bedc45f4312fb454..df570e5c71cc6b8f696ac44d225529e17703876d 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -436,67 +436,25 @@ static void shrink_zone_span(struct zone *zone, unsigned long start_pfn, zone_span_writeunlock(zone); } -static void shrink_pgdat_span(struct pglist_data *pgdat, - unsigned long start_pfn, unsigned long end_pfn) +static void update_pgdat_span(struct pglist_data *pgdat) { - unsigned long pgdat_start_pfn = pgdat->node_start_pfn; - unsigned long p = pgdat_end_pfn(pgdat); /* pgdat_end_pfn namespace clash */ - unsigned long pgdat_end_pfn = p; - unsigned long pfn; - int nid = pgdat->node_id; - - if (pgdat_start_pfn == start_pfn) { - /* - * If the section is smallest section in the pgdat, it need - * shrink pgdat->node_start_pfn and pgdat->node_spanned_pages. - * In this case, we find second smallest valid mem_section - * for shrinking zone. - */ - pfn = find_smallest_section_pfn(nid, NULL, end_pfn, - pgdat_end_pfn); - if (pfn) { - pgdat->node_start_pfn = pfn; - pgdat->node_spanned_pages = pgdat_end_pfn - pfn; - } - } else if (pgdat_end_pfn == end_pfn) { - /* - * If the section is biggest section in the pgdat, it need - * shrink pgdat->node_spanned_pages. - * In this case, we find second biggest valid mem_section for - * shrinking zone. - */ - pfn = find_biggest_section_pfn(nid, NULL, pgdat_start_pfn, - start_pfn); - if (pfn) - pgdat->node_spanned_pages = pfn - pgdat_start_pfn + 1; - } - - /* - * If the section is not biggest or smallest mem_section in the pgdat, - * it only creates a hole in the pgdat. So in this case, we need not - * change the pgdat. - * But perhaps, the pgdat has only hole data. Thus it check the pgdat - * has only hole or not. - */ - pfn = pgdat_start_pfn; - for (; pfn < pgdat_end_pfn; pfn += PAGES_PER_SUBSECTION) { - if (unlikely(!pfn_valid(pfn))) - continue; - - if (pfn_to_nid(pfn) != nid) - continue; + unsigned long node_start_pfn = 0, node_end_pfn = 0; + struct zone *zone; - /* Skip range to be removed */ - if (pfn >= start_pfn && pfn < end_pfn) - continue; + for (zone = pgdat->node_zones; + zone < pgdat->node_zones + MAX_NR_ZONES; zone++) { + unsigned long zone_end_pfn = zone->zone_start_pfn + + zone->spanned_pages; - /* If we find valid section, we have nothing to do */ - return; + /* No need to lock the zones, they can't change. */ + if (zone_end_pfn > node_end_pfn) + node_end_pfn = zone_end_pfn; + if (zone->zone_start_pfn < node_start_pfn) + node_start_pfn = zone->zone_start_pfn; } - /* The pgdat has no valid section */ - pgdat->node_start_pfn = 0; - pgdat->node_spanned_pages = 0; + pgdat->node_start_pfn = node_start_pfn; + pgdat->node_spanned_pages = node_end_pfn - node_start_pfn; } static void __remove_zone(struct zone *zone, unsigned long start_pfn, @@ -507,7 +465,7 @@ static void __remove_zone(struct zone *zone, unsigned long start_pfn, pgdat_resize_lock(zone->zone_pgdat, &flags); shrink_zone_span(zone, start_pfn, start_pfn + nr_pages); - shrink_pgdat_span(pgdat, start_pfn, start_pfn + nr_pages); + update_pgdat_span(pgdat); pgdat_resize_unlock(zone->zone_pgdat, &flags); } diff --git a/mm/memremap.c b/mm/memremap.c index 68204912cc0a1ffe875de0a398fa1152febdb811..03ccbdfeb6972018eea805d5848b4a9b3a3ba4cd 100644 --- a/mm/memremap.c +++ b/mm/memremap.c @@ -103,6 +103,7 @@ static void dev_pagemap_cleanup(struct dev_pagemap *pgmap) void memunmap_pages(struct dev_pagemap *pgmap) { struct resource *res = &pgmap->res; + struct page *first_page; unsigned long pfn; int nid; @@ -111,14 +112,16 @@ void memunmap_pages(struct dev_pagemap *pgmap) put_page(pfn_to_page(pfn)); dev_pagemap_cleanup(pgmap); + /* make sure to access a memmap that was actually initialized */ + first_page = pfn_to_page(pfn_first(pgmap)); + /* pages are dead and unused, undo the arch mapping */ - nid = page_to_nid(pfn_to_page(PHYS_PFN(res->start))); + nid = page_to_nid(first_page); mem_hotplug_begin(); if (pgmap->type == MEMORY_DEVICE_PRIVATE) { - pfn = PHYS_PFN(res->start); - __remove_pages(page_zone(pfn_to_page(pfn)), pfn, - PHYS_PFN(resource_size(res)), NULL); + __remove_pages(page_zone(first_page), PHYS_PFN(res->start), + PHYS_PFN(resource_size(res)), NULL); } else { arch_remove_memory(nid, res->start, resource_size(res), pgmap_altmap(pgmap)); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 43d3c2684735ec8d47a90c9b61820e4d9a40d40c..2725b1681adb757f4f456aa6cdb4701bf065144d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4487,12 +4487,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, if (page) goto got_pg; - if (order >= pageblock_order && (gfp_mask & __GFP_IO)) { + if (order >= pageblock_order && (gfp_mask & __GFP_IO) && + !(gfp_mask & __GFP_RETRY_MAYFAIL)) { /* * If allocating entire pageblock(s) and compaction * failed because all zones are below low watermarks * or is prohibited because it recently failed at this - * order, fail immediately. + * order, fail immediately unless the allocator has + * requested compaction and reclaim retry. * * Reclaim is * - potentially very expensive because zones are far diff --git a/mm/page_ext.c b/mm/page_ext.c index 5f5769c7db3b2f87b78ebc0b07425edecc7d0846..4ade843ff58846cc9f73d3cb54ce78849643ca71 100644 --- a/mm/page_ext.c +++ b/mm/page_ext.c @@ -67,8 +67,9 @@ static struct page_ext_operations *page_ext_ops[] = { #endif }; +unsigned long page_ext_size = sizeof(struct page_ext); + static unsigned long total_usage; -static unsigned long extra_mem; static bool __init invoke_need_callbacks(void) { @@ -78,9 +79,8 @@ static bool __init invoke_need_callbacks(void) for (i = 0; i < entries; i++) { if (page_ext_ops[i]->need && page_ext_ops[i]->need()) { - page_ext_ops[i]->offset = sizeof(struct page_ext) + - extra_mem; - extra_mem += page_ext_ops[i]->size; + page_ext_ops[i]->offset = page_ext_size; + page_ext_size += page_ext_ops[i]->size; need = true; } } @@ -99,14 +99,9 @@ static void __init invoke_init_callbacks(void) } } -static unsigned long get_entry_size(void) -{ - return sizeof(struct page_ext) + extra_mem; -} - static inline struct page_ext *get_entry(void *base, unsigned long index) { - return base + get_entry_size() * index; + return base + page_ext_size * index; } #if !defined(CONFIG_SPARSEMEM) @@ -156,7 +151,7 @@ static int __init alloc_node_page_ext(int nid) !IS_ALIGNED(node_end_pfn(nid), MAX_ORDER_NR_PAGES)) nr_pages += MAX_ORDER_NR_PAGES; - table_size = get_entry_size() * nr_pages; + table_size = page_ext_size * nr_pages; base = memblock_alloc_try_nid( table_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS), @@ -234,7 +229,7 @@ static int __meminit init_section_page_ext(unsigned long pfn, int nid) if (section->page_ext) return 0; - table_size = get_entry_size() * PAGES_PER_SECTION; + table_size = page_ext_size * PAGES_PER_SECTION; base = alloc_page_ext(table_size, nid); /* @@ -254,7 +249,7 @@ static int __meminit init_section_page_ext(unsigned long pfn, int nid) * we need to apply a mask. */ pfn &= PAGE_SECTION_MASK; - section->page_ext = (void *)base - get_entry_size() * pfn; + section->page_ext = (void *)base - page_ext_size * pfn; total_usage += table_size; return 0; } @@ -267,7 +262,7 @@ static void free_page_ext(void *addr) struct page *page = virt_to_page(addr); size_t table_size; - table_size = get_entry_size() * PAGES_PER_SECTION; + table_size = page_ext_size * PAGES_PER_SECTION; BUG_ON(PageReserved(page)); kmemleak_free(addr); diff --git a/mm/page_owner.c b/mm/page_owner.c index 50eef17ae8c8eab2bc305061d691c5f5ec352fa9..03176b5f7bfcafda5482e0bb0d606fcf45d563e2 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -24,13 +24,10 @@ struct page_owner { short last_migrate_reason; gfp_t gfp_mask; depot_stack_handle_t handle; -#ifdef CONFIG_DEBUG_PAGEALLOC depot_stack_handle_t free_handle; -#endif }; -static bool page_owner_disabled = - !IS_ENABLED(CONFIG_PAGE_OWNER_ENABLE_DEFAULT); +static bool page_owner_enabled = IS_ENABLED(CONFIG_PAGE_OWNER_ENABLE_DEFAULT); DEFINE_STATIC_KEY_FALSE(page_owner_inited); static depot_stack_handle_t dummy_handle; @@ -45,10 +42,10 @@ static int __init early_page_owner_param(char *buf) return -EINVAL; if (strcmp(buf, "on") == 0) - page_owner_disabled = false; + page_owner_enabled = true; if (strcmp(buf, "off") == 0) - page_owner_disabled = true; + page_owner_enabled = false; return 0; } @@ -56,10 +53,7 @@ early_param("page_owner", early_page_owner_param); static bool need_page_owner(void) { - if (page_owner_disabled) - return false; - - return true; + return page_owner_enabled; } static __always_inline depot_stack_handle_t create_dummy_stack(void) @@ -88,7 +82,7 @@ static noinline void register_early_stack(void) static void init_page_owner(void) { - if (page_owner_disabled) + if (!page_owner_enabled) return; register_dummy_stack(); @@ -152,25 +146,19 @@ void __reset_page_owner(struct page *page, unsigned int order) { int i; struct page_ext *page_ext; -#ifdef CONFIG_DEBUG_PAGEALLOC depot_stack_handle_t handle = 0; struct page_owner *page_owner; - if (debug_pagealloc_enabled()) - handle = save_stack(GFP_NOWAIT | __GFP_NOWARN); -#endif + handle = save_stack(GFP_NOWAIT | __GFP_NOWARN); + page_ext = lookup_page_ext(page); + if (unlikely(!page_ext)) + return; for (i = 0; i < (1 << order); i++) { - page_ext = lookup_page_ext(page + i); - if (unlikely(!page_ext)) - continue; - __clear_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags); -#ifdef CONFIG_DEBUG_PAGEALLOC - if (debug_pagealloc_enabled()) { - page_owner = get_page_owner(page_ext); - page_owner->free_handle = handle; - } -#endif + __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); + page_owner = get_page_owner(page_ext); + page_owner->free_handle = handle; + page_ext = page_ext_next(page_ext); } } @@ -188,9 +176,9 @@ static inline void __set_page_owner_handle(struct page *page, page_owner->gfp_mask = gfp_mask; page_owner->last_migrate_reason = -1; __set_bit(PAGE_EXT_OWNER, &page_ext->flags); - __set_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags); + __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); - page_ext = lookup_page_ext(page + i); + page_ext = page_ext_next(page_ext); } } @@ -228,12 +216,10 @@ void __split_page_owner(struct page *page, unsigned int order) if (unlikely(!page_ext)) return; - page_owner = get_page_owner(page_ext); - page_owner->order = 0; - for (i = 1; i < (1 << order); i++) { - page_ext = lookup_page_ext(page + i); + for (i = 0; i < (1 << order); i++) { page_owner = get_page_owner(page_ext); page_owner->order = 0; + page_ext = page_ext_next(page_ext); } } @@ -264,7 +250,7 @@ void __copy_page_owner(struct page *oldpage, struct page *newpage) * the new page, which will be freed. */ __set_bit(PAGE_EXT_OWNER, &new_ext->flags); - __set_bit(PAGE_EXT_OWNER_ACTIVE, &new_ext->flags); + __set_bit(PAGE_EXT_OWNER_ALLOCATED, &new_ext->flags); } void pagetypeinfo_showmixedcount_print(struct seq_file *m, @@ -288,7 +274,8 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m, * not matter as the mixed block count will still be correct */ for (; pfn < end_pfn; ) { - if (!pfn_valid(pfn)) { + page = pfn_to_online_page(pfn); + if (!page) { pfn = ALIGN(pfn + 1, MAX_ORDER_NR_PAGES); continue; } @@ -296,13 +283,13 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m, block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); block_end_pfn = min(block_end_pfn, end_pfn); - page = pfn_to_page(pfn); pageblock_mt = get_pageblock_migratetype(page); for (; pfn < block_end_pfn; pfn++) { if (!pfn_valid_within(pfn)) continue; + /* The pageblock is online, no need to recheck. */ page = pfn_to_page(pfn); if (page_zone(page) != zone) @@ -324,7 +311,7 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m, if (unlikely(!page_ext)) continue; - if (!test_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags)) + if (!test_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags)) continue; page_owner = get_page_owner(page_ext); @@ -439,7 +426,7 @@ void __dump_page_owner(struct page *page) return; } - if (test_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags)) + if (test_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags)) pr_alert("page_owner tracks the page as allocated\n"); else pr_alert("page_owner tracks the page as freed\n"); @@ -455,7 +442,6 @@ void __dump_page_owner(struct page *page) stack_trace_print(entries, nr_entries, 0); } -#ifdef CONFIG_DEBUG_PAGEALLOC handle = READ_ONCE(page_owner->free_handle); if (!handle) { pr_alert("page_owner free stack trace missing\n"); @@ -464,7 +450,6 @@ void __dump_page_owner(struct page *page) pr_alert("page last free stack trace:\n"); stack_trace_print(entries, nr_entries, 0); } -#endif if (page_owner->last_migrate_reason != -1) pr_alert("page has been migrated, last migrate reason: %s\n", @@ -531,7 +516,7 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) * Although we do have the info about past allocation of free * pages, it's not relevant for current memory usage. */ - if (!test_bit(PAGE_EXT_OWNER_ACTIVE, &page_ext->flags)) + if (!test_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags)) continue; page_owner = get_page_owner(page_ext); diff --git a/mm/rmap.c b/mm/rmap.c index d9a23bb773bf7997773cb94952fbf73c313a0bf3..0c7b2a9400d4a286799d76381f8188250bf72528 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include diff --git a/mm/slab.c b/mm/slab.c index 9df370558e5d25fbfb073e58c666b72bcaf8a165..66e5d8032bae4a046cd2b30293b5bf7edadad485 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4206,9 +4206,12 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page, /** * __ksize -- Uninstrumented ksize. + * @objp: pointer to the object * * Unlike ksize(), __ksize() is uninstrumented, and does not provide the same * safety checks as ksize() with KASAN instrumentation enabled. + * + * Return: size of the actual memory used by @objp in bytes */ size_t __ksize(const void *objp) { diff --git a/mm/slab_common.c b/mm/slab_common.c index c29f03adca91cef1374aedd2907281f4a4af0f14..f9fb27b4c84398c49eee6b9a46e006d5c2c28f95 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -178,10 +178,13 @@ static int init_memcg_params(struct kmem_cache *s, static void destroy_memcg_params(struct kmem_cache *s) { - if (is_root_cache(s)) + if (is_root_cache(s)) { kvfree(rcu_access_pointer(s->memcg_params.memcg_caches)); - else + } else { + mem_cgroup_put(s->memcg_params.memcg); + WRITE_ONCE(s->memcg_params.memcg, NULL); percpu_ref_exit(&s->memcg_params.refcnt); + } } static void free_memcg_params(struct rcu_head *rcu) @@ -253,8 +256,6 @@ static void memcg_unlink_cache(struct kmem_cache *s) } else { list_del(&s->memcg_params.children_node); list_del(&s->memcg_params.kmem_caches_node); - mem_cgroup_put(s->memcg_params.memcg); - WRITE_ONCE(s->memcg_params.memcg, NULL); } } #else diff --git a/mm/slub.c b/mm/slub.c index a7dd51f060a28d8a240150d35730f1baa96e17e2..a830f4fc6c81056eb3449d309a77be391ceec92e 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2680,6 +2680,17 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, return p; } +/* + * If the object has been wiped upon free, make sure it's fully initialized by + * zeroing out freelist pointer. + */ +static __always_inline void maybe_wipe_obj_freeptr(struct kmem_cache *s, + void *obj) +{ + if (unlikely(slab_want_init_on_free(s)) && obj) + memset((void *)((char *)obj + s->offset), 0, sizeof(void *)); +} + /* * Inlined fastpath so that allocation functions (kmalloc, kmem_cache_alloc) * have the fastpath folded into their functions. So no function call @@ -2768,12 +2779,8 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, prefetch_freepointer(s, next_object); stat(s, ALLOC_FASTPATH); } - /* - * If the object has been wiped upon free, make sure it's fully - * initialized by zeroing out freelist pointer. - */ - if (unlikely(slab_want_init_on_free(s)) && object) - memset(object + s->offset, 0, sizeof(void *)); + + maybe_wipe_obj_freeptr(s, object); if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object) memset(object, 0, s->object_size); @@ -3187,10 +3194,13 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size, goto error; c = this_cpu_ptr(s->cpu_slab); + maybe_wipe_obj_freeptr(s, p[i]); + continue; /* goto for-loop */ } c->freelist = get_freepointer(s, object); p[i] = object; + maybe_wipe_obj_freeptr(s, p[i]); } c->tid = next_tid(c->tid); local_irq_enable(); @@ -4855,7 +4865,17 @@ static ssize_t show_slab_objects(struct kmem_cache *s, } } - get_online_mems(); + /* + * It is impossible to take "mem_hotplug_lock" here with "kernfs_mutex" + * already held which will conflict with an existing lock order: + * + * mem_hotplug_lock->slab_mutex->kernfs_mutex + * + * We don't really need mem_hotplug_lock (to hold off + * slab_mem_going_offline_callback) here because slab's memory hot + * unplug code doesn't destroy the kmem_cache->node[] data. + */ + #ifdef CONFIG_SLUB_DEBUG if (flags & SO_ALL) { struct kmem_cache_node *n; @@ -4896,7 +4916,6 @@ static ssize_t show_slab_objects(struct kmem_cache *s, x += sprintf(buf + x, " N%d=%lu", node, nodes[node]); #endif - put_online_mems(); kfree(nodes); return x + sprintf(buf + x, "\n"); } diff --git a/mm/truncate.c b/mm/truncate.c index 8563339041f68c4a602ab364f913636071ccda70..dd9ebc1da35664d04dd508539b34fb96dc764f28 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -592,6 +592,16 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, unlock_page(page); continue; } + + /* Take a pin outside pagevec */ + get_page(page); + + /* + * Drop extra pins before trying to invalidate + * the huge page. + */ + pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); } ret = invalidate_inode_page(page); @@ -602,6 +612,8 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, */ if (!ret) deactivate_file_page(page); + if (PageTransHuge(page)) + put_page(page); count += ret; } pagevec_remove_exceptionals(&pvec); diff --git a/mm/vmscan.c b/mm/vmscan.c index 35755b8351cc72063f6ad1eb300dba7fdeb4e394..0dfbd8c424f8a70ae43f1166cfde10adc0b0cc81 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -351,12 +351,13 @@ unsigned long zone_reclaimable_pages(struct zone *zone) */ unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru, int zone_idx) { - unsigned long lru_size; + unsigned long lru_size = 0; int zid; - if (!mem_cgroup_disabled()) - lru_size = lruvec_page_state_local(lruvec, NR_LRU_BASE + lru); - else + if (!mem_cgroup_disabled()) { + for (zid = 0; zid < MAX_NR_ZONES; zid++) + lru_size += mem_cgroup_get_zone_lru_size(lruvec, lru, zid); + } else lru_size = node_page_state(lruvec_pgdat(lruvec), NR_LRU_BASE + lru); for (zid = zone_idx + 1; zid < MAX_NR_ZONES; zid++) { @@ -936,10 +937,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, * Note that if SetPageDirty is always performed via set_page_dirty, * and thus under the i_pages lock, then this ordering is not required. */ - if (unlikely(PageTransHuge(page)) && PageSwapCache(page)) - refcount = 1 + HPAGE_PMD_NR; - else - refcount = 2; + refcount = 1 + compound_nr(page); if (!page_ref_freeze(page, refcount)) goto cannot_free; /* note: atomic_cmpxchg in page_ref_freeze provides the smp_rmb */ diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 54728d2eda189d870ecb97acd0278fdca4358761..d4bcfd8f95bf6435902e10cce19fc43b47d867d9 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -172,7 +172,6 @@ int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack) if (err < 0) goto out_uninit_mvrp; - vlan->nest_level = dev_get_nest_level(real_dev) + 1; err = register_netdevice(dev); if (err < 0) goto out_uninit_mvrp; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 93eadf1791239fd8eb81d4724ae37c7b959e5ca9..e5bff5cc6f97562a9887195ced5c572c1951915e 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -489,36 +489,6 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); } -/* - * vlan network devices have devices nesting below it, and are a special - * "super class" of normal network devices; split their locks off into a - * separate class since they always nest. - */ -static struct lock_class_key vlan_netdev_xmit_lock_key; -static struct lock_class_key vlan_netdev_addr_lock_key; - -static void vlan_dev_set_lockdep_one(struct net_device *dev, - struct netdev_queue *txq, - void *_subclass) -{ - lockdep_set_class_and_subclass(&txq->_xmit_lock, - &vlan_netdev_xmit_lock_key, - *(int *)_subclass); -} - -static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass) -{ - lockdep_set_class_and_subclass(&dev->addr_list_lock, - &vlan_netdev_addr_lock_key, - subclass); - netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass); -} - -static int vlan_dev_get_lock_subclass(struct net_device *dev) -{ - return vlan_dev_priv(dev)->nest_level; -} - static const struct header_ops vlan_header_ops = { .create = vlan_dev_hard_header, .parse = eth_header_parse, @@ -609,8 +579,6 @@ static int vlan_dev_init(struct net_device *dev) SET_NETDEV_DEVTYPE(dev, &vlan_type); - vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev)); - vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); if (!vlan->vlan_pcpu_stats) return -ENOMEM; @@ -812,7 +780,6 @@ static const struct net_device_ops vlan_netdev_ops = { .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, #endif .ndo_fix_features = vlan_dev_fix_features, - .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, .ndo_get_iflink = vlan_dev_get_iflink, }; diff --git a/net/atm/common.c b/net/atm/common.c index b7528e77997c88b7cf15f0b48412e3abef0620e3..0ce530af534ddfed26a32b1b24f202ee7c582198 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -668,7 +668,7 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) mask |= EPOLLHUP; /* readable? */ - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; /* writable? */ diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index d78938e3e0085d9cff138b805148a0e77de3f654..5b0b20e6da956b4333b118bce1c09c5acef6d66f 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -193,14 +195,18 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) unsigned char *ogm_buff; u32 random_seqno; + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + /* randomize initial seqno to avoid collision */ get_random_bytes(&random_seqno, sizeof(random_seqno)); atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno); hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN; ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC); - if (!ogm_buff) + if (!ogm_buff) { + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); return -ENOMEM; + } hard_iface->bat_iv.ogm_buff = ogm_buff; @@ -212,35 +218,59 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) batadv_ogm_packet->reserved = 0; batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); + return 0; } static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) { + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + kfree(hard_iface->bat_iv.ogm_buff); hard_iface->bat_iv.ogm_buff = NULL; + + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); } static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) { struct batadv_ogm_packet *batadv_ogm_packet; - unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; + void *ogm_buff; - batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + + ogm_buff = hard_iface->bat_iv.ogm_buff; + if (!ogm_buff) + goto unlock; + + batadv_ogm_packet = ogm_buff; ether_addr_copy(batadv_ogm_packet->orig, hard_iface->net_dev->dev_addr); ether_addr_copy(batadv_ogm_packet->prev_sender, hard_iface->net_dev->dev_addr); + +unlock: + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); } static void batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) { struct batadv_ogm_packet *batadv_ogm_packet; - unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; + void *ogm_buff; - batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + + ogm_buff = hard_iface->bat_iv.ogm_buff; + if (!ogm_buff) + goto unlock; + + batadv_ogm_packet = ogm_buff; batadv_ogm_packet->ttl = BATADV_TTL; + +unlock: + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); } /* when do we schedule our own ogm to be sent */ @@ -742,7 +772,11 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface) } } -static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) +/** + * batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer + * @hard_iface: interface whose ogm buffer should be transmitted + */ +static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff; @@ -753,9 +787,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) u16 tvlv_len = 0; unsigned long send_time; - if (hard_iface->if_status == BATADV_IF_NOT_IN_USE || - hard_iface->if_status == BATADV_IF_TO_BE_REMOVED) - return; + lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex); /* the interface gets activated here to avoid race conditions between * the moment of activating the interface in @@ -823,6 +855,17 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) batadv_hardif_put(primary_if); } +static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) +{ + if (hard_iface->if_status == BATADV_IF_NOT_IN_USE || + hard_iface->if_status == BATADV_IF_TO_BE_REMOVED) + return; + + mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + batadv_iv_ogm_schedule_buff(hard_iface); + mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); +} + /** * batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over iterface * @orig_node: originator which reproadcasted the OGMs directly diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index dc4f7430cb5a6528ac4635c943ab4d65db1a538b..8033f24f506cae2d734aea5296cb5bd3066e7277 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -256,14 +257,12 @@ static void batadv_v_ogm_queue_on_if(struct sk_buff *skb, } /** - * batadv_v_ogm_send() - periodic worker broadcasting the own OGM - * @work: work queue item + * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM + * @bat_priv: the bat priv with all the soft interface information */ -static void batadv_v_ogm_send(struct work_struct *work) +static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv) { struct batadv_hard_iface *hard_iface; - struct batadv_priv_bat_v *bat_v; - struct batadv_priv *bat_priv; struct batadv_ogm2_packet *ogm_packet; struct sk_buff *skb, *skb_tmp; unsigned char *ogm_buff; @@ -271,8 +270,7 @@ static void batadv_v_ogm_send(struct work_struct *work) u16 tvlv_len = 0; int ret; - bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); - bat_priv = container_of(bat_v, struct batadv_priv, bat_v); + lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex); if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) goto out; @@ -363,6 +361,23 @@ static void batadv_v_ogm_send(struct work_struct *work) return; } +/** + * batadv_v_ogm_send() - periodic worker broadcasting the own OGM + * @work: work queue item + */ +static void batadv_v_ogm_send(struct work_struct *work) +{ + struct batadv_priv_bat_v *bat_v; + struct batadv_priv *bat_priv; + + bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); + bat_priv = container_of(bat_v, struct batadv_priv, bat_v); + + mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); + batadv_v_ogm_send_softif(bat_priv); + mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); +} + /** * batadv_v_ogm_aggr_work() - OGM queue periodic task per interface * @work: work queue item @@ -424,11 +439,15 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface) struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface); struct batadv_ogm2_packet *ogm_packet; + mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); if (!bat_priv->bat_v.ogm_buff) - return; + goto unlock; ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff; ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr); + +unlock: + mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); } /** @@ -1050,6 +1069,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv) atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno); INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send); + mutex_init(&bat_priv->bat_v.ogm_buff_mutex); + return 0; } @@ -1061,7 +1082,11 @@ void batadv_v_ogm_free(struct batadv_priv *bat_priv) { cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq); + mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); + kfree(bat_priv->bat_v.ogm_buff); bat_priv->bat_v.ogm_buff = NULL; bat_priv->bat_v.ogm_buff_len = 0; + + mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); } diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index c90e47342bb0698ae460efe7f8ca35bd313d6cce..afb52282d5bd0d495febb5b7d636830f5475d74e 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -929,6 +930,7 @@ batadv_hardif_add_interface(struct net_device *net_dev) INIT_LIST_HEAD(&hard_iface->list); INIT_HLIST_HEAD(&hard_iface->neigh_list); + mutex_init(&hard_iface->bat_iv.ogm_buff_mutex); spin_lock_init(&hard_iface->neigh_list_lock); kref_init(&hard_iface->refcount); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9cbed6f5a85a61640de1bb14b6e20ed13db352a9..5ee8e9a100f903d01fb6799828dfba6ae416ec66 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -740,36 +740,6 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto, return 0; } -/* batman-adv network devices have devices nesting below it and are a special - * "super class" of normal network devices; split their locks off into a - * separate class since they always nest. - */ -static struct lock_class_key batadv_netdev_xmit_lock_key; -static struct lock_class_key batadv_netdev_addr_lock_key; - -/** - * batadv_set_lockdep_class_one() - Set lockdep class for a single tx queue - * @dev: device which owns the tx queue - * @txq: tx queue to modify - * @_unused: always NULL - */ -static void batadv_set_lockdep_class_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key); -} - -/** - * batadv_set_lockdep_class() - Set txq and addr_list lockdep class - * @dev: network device to modify - */ -static void batadv_set_lockdep_class(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key); - netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL); -} - /** * batadv_softif_init_late() - late stage initialization of soft interface * @dev: registered network device to modify @@ -783,8 +753,6 @@ static int batadv_softif_init_late(struct net_device *dev) int ret; size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM; - batadv_set_lockdep_class(dev); - bat_priv = netdev_priv(dev); bat_priv->soft_iface = dev; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index be7c02aa91e26dcc8d0c322fa162b0dd3a5a0eb9..4d7f1baee7b7da7d32060014400e89db9c7f0b7a 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include /* for linux/wait.h */ @@ -81,6 +82,9 @@ struct batadv_hard_iface_bat_iv { /** @ogm_seqno: OGM sequence number - used to identify each OGM */ atomic_t ogm_seqno; + + /** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */ + struct mutex ogm_buff_mutex; }; /** @@ -1539,6 +1543,9 @@ struct batadv_priv_bat_v { /** @ogm_seqno: OGM sequence number - used to identify each OGM */ atomic_t ogm_seqno; + /** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */ + struct mutex ogm_buff_mutex; + /** @ogm_wq: workqueue used to schedule OGM transmissions */ struct delayed_work ogm_wq; }; diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index bb55d92691b068d32b281b1b3ceff58b8ac51fc4..4febc82a7c7613244125696cfd464099e10991dc 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -571,15 +571,7 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) return err < 0 ? NET_XMIT_DROP : err; } -static int bt_dev_init(struct net_device *dev) -{ - netdev_lockdep_set_classes(dev); - - return 0; -} - static const struct net_device_ops netdev_ops = { - .ndo_init = bt_dev_init, .ndo_start_xmit = bt_xmit, }; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 94ddf19998c7ee7098b52c9ef37f3e0296089fab..5f508c50649d0abc317ed83cc0768f6b7a64de96 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -460,7 +460,7 @@ __poll_t bt_sock_poll(struct file *file, struct socket *sock, if (sk->sk_state == BT_LISTEN) return bt_accept_poll(sk); - if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) + if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) mask |= EPOLLERR | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0); @@ -470,7 +470,7 @@ __poll_t bt_sock_poll(struct file *file, struct socket *sock, if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= EPOLLHUP; - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; if (sk->sk_state == BT_CLOSED) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 681b72862c165558e756afacda786998a0e9f185..e804a3016902b741205366b5e9876a094f9f5856 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -24,8 +24,6 @@ const struct nf_br_ops __rcu *nf_br_ops __read_mostly; EXPORT_SYMBOL_GPL(nf_br_ops); -static struct lock_class_key bridge_netdev_addr_lock_key; - /* net device transmit always called with BH disabled */ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -108,11 +106,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static void br_set_lockdep_class(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key); -} - static int br_dev_init(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); @@ -150,7 +143,6 @@ static int br_dev_init(struct net_device *dev) br_mdb_hash_fini(br); br_fdb_hash_fini(br); } - br_set_lockdep_class(dev); return err; } diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c index 8842798c29e636ac2dbfe01f0bf2ba2f2d398c44..8096732223828a7110ab35d715fe1894ddf57a91 100644 --- a/net/bridge/netfilter/nf_conntrack_bridge.c +++ b/net/bridge/netfilter/nf_conntrack_bridge.c @@ -33,6 +33,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, { int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; unsigned int hlen, ll_rs, mtu; + ktime_t tstamp = skb->tstamp; struct ip_frag_state state; struct iphdr *iph; int err; @@ -80,6 +81,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, if (iter.frag) ip_fraglist_prepare(skb, &iter); + skb->tstamp = tstamp; err = output(net, sk, data, skb); if (err || !iter.frag) break; @@ -93,7 +95,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, * This may also be a clone skbuff, we could preserve the geometry for * the copies but probably not worth the effort. */ - ip_frag_init(skb, hlen, ll_rs, frag_max_size, &state); + ip_frag_init(skb, hlen, ll_rs, frag_max_size, false, &state); while (state.left > 0) { struct sk_buff *skb2; @@ -104,6 +106,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, goto blackhole; } + skb2->tstamp = tstamp; err = output(net, sk, data, skb2); if (err) goto blackhole; diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 13ea920600aeb66af017134cbe5fcfd5ccc6020e..ef14da50a9819183c538f14b97b5e4986adafb45 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -953,7 +953,7 @@ static __poll_t caif_poll(struct file *file, mask |= EPOLLRDHUP; /* readable? */ - if (!skb_queue_empty(&sk->sk_receive_queue) || + if (!skb_queue_empty_lockless(&sk->sk_receive_queue) || (sk->sk_shutdown & RCV_SHUTDOWN)) mask |= EPOLLIN | EPOLLRDNORM; diff --git a/net/core/datagram.c b/net/core/datagram.c index 4cc8dc5db2b73471ae3a15fda753912d5e869624..da3c24ed129cd64db8bdb1916afa552a47c1a5a3 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -97,7 +97,7 @@ int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p, if (error) goto out_err; - if (sk->sk_receive_queue.prev != skb) + if (READ_ONCE(sk->sk_receive_queue.prev) != skb) goto out; /* Socket shut down? */ @@ -278,7 +278,7 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags, break; sk_busy_loop(sk, flags & MSG_DONTWAIT); - } while (sk->sk_receive_queue.prev != *last); + } while (READ_ONCE(sk->sk_receive_queue.prev) != *last); error = -EAGAIN; @@ -640,7 +640,7 @@ int __zerocopy_sg_from_iter(struct sock *sk, struct sk_buff *skb, skb->len += copied; skb->truesize += truesize; if (sk && sk->sk_type == SOCK_STREAM) { - sk->sk_wmem_queued += truesize; + sk_wmem_queued_add(sk, truesize); sk_mem_charge(sk, truesize); } else { refcount_add(truesize, &skb->sk->sk_wmem_alloc); @@ -767,7 +767,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock, mask = 0; /* exceptional events? */ - if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) + if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) mask |= EPOLLERR | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0); @@ -777,7 +777,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock, mask |= EPOLLHUP; /* readable? */ - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; /* Connection-based need to check for termination and startup */ diff --git a/net/core/dev.c b/net/core/dev.c index bf3ed413abafe121d8c20ea4ca023ea770c111cc..99ac84ff398f42ff171d5882991724f2f4df11a4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -146,6 +146,7 @@ #include "net-sysfs.h" #define MAX_GRO_SKBS 8 +#define MAX_NEST_DEV 8 /* This should be increased if a protocol with a bigger head is added. */ #define GRO_MAX_HEAD (MAX_HEADER + 128) @@ -276,88 +277,6 @@ static RAW_NOTIFIER_HEAD(netdev_chain); DEFINE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); EXPORT_PER_CPU_SYMBOL(softnet_data); -#ifdef CONFIG_LOCKDEP -/* - * register_netdevice() inits txq->_xmit_lock and sets lockdep class - * according to dev->type - */ -static const unsigned short netdev_lock_type[] = { - ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25, - ARPHRD_PRONET, ARPHRD_CHAOS, ARPHRD_IEEE802, ARPHRD_ARCNET, - ARPHRD_APPLETLK, ARPHRD_DLCI, ARPHRD_ATM, ARPHRD_METRICOM, - ARPHRD_IEEE1394, ARPHRD_EUI64, ARPHRD_INFINIBAND, ARPHRD_SLIP, - ARPHRD_CSLIP, ARPHRD_SLIP6, ARPHRD_CSLIP6, ARPHRD_RSRVD, - ARPHRD_ADAPT, ARPHRD_ROSE, ARPHRD_X25, ARPHRD_HWX25, - ARPHRD_PPP, ARPHRD_CISCO, ARPHRD_LAPB, ARPHRD_DDCMP, - ARPHRD_RAWHDLC, ARPHRD_TUNNEL, ARPHRD_TUNNEL6, ARPHRD_FRAD, - ARPHRD_SKIP, ARPHRD_LOOPBACK, ARPHRD_LOCALTLK, ARPHRD_FDDI, - ARPHRD_BIF, ARPHRD_SIT, ARPHRD_IPDDP, ARPHRD_IPGRE, - ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET, - ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, - ARPHRD_FCFABRIC, ARPHRD_IEEE80211, ARPHRD_IEEE80211_PRISM, - ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, ARPHRD_PHONET_PIPE, - ARPHRD_IEEE802154, ARPHRD_VOID, ARPHRD_NONE}; - -static const char *const netdev_lock_name[] = { - "_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25", - "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET", - "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM", - "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP", - "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD", - "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25", - "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP", - "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD", - "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI", - "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE", - "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET", - "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL", - "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM", - "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE", - "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"}; - -static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)]; -static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)]; - -static inline unsigned short netdev_lock_pos(unsigned short dev_type) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(netdev_lock_type); i++) - if (netdev_lock_type[i] == dev_type) - return i; - /* the last key is used by default */ - return ARRAY_SIZE(netdev_lock_type) - 1; -} - -static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, - unsigned short dev_type) -{ - int i; - - i = netdev_lock_pos(dev_type); - lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i], - netdev_lock_name[i]); -} - -static inline void netdev_set_addr_lockdep_class(struct net_device *dev) -{ - int i; - - i = netdev_lock_pos(dev->type); - lockdep_set_class_and_name(&dev->addr_list_lock, - &netdev_addr_lock_key[i], - netdev_lock_name[i]); -} -#else -static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, - unsigned short dev_type) -{ -} -static inline void netdev_set_addr_lockdep_class(struct net_device *dev) -{ -} -#endif - /******************************************************************************* * * Protocol management and registration routines @@ -6489,6 +6408,9 @@ struct netdev_adjacent { /* upper master flag, there can only be one master device per list */ bool master; + /* lookup ignore flag */ + bool ignore; + /* counter for the number of times this device was added to us */ u16 ref_nr; @@ -6511,7 +6433,7 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *adj_dev, return NULL; } -static int __netdev_has_upper_dev(struct net_device *upper_dev, void *data) +static int ____netdev_has_upper_dev(struct net_device *upper_dev, void *data) { struct net_device *dev = data; @@ -6532,7 +6454,7 @@ bool netdev_has_upper_dev(struct net_device *dev, { ASSERT_RTNL(); - return netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev, + return netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev, upper_dev); } EXPORT_SYMBOL(netdev_has_upper_dev); @@ -6550,7 +6472,7 @@ EXPORT_SYMBOL(netdev_has_upper_dev); bool netdev_has_upper_dev_all_rcu(struct net_device *dev, struct net_device *upper_dev) { - return !!netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev, + return !!netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev, upper_dev); } EXPORT_SYMBOL(netdev_has_upper_dev_all_rcu); @@ -6594,6 +6516,22 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev) } EXPORT_SYMBOL(netdev_master_upper_dev_get); +static struct net_device *__netdev_master_upper_dev_get(struct net_device *dev) +{ + struct netdev_adjacent *upper; + + ASSERT_RTNL(); + + if (list_empty(&dev->adj_list.upper)) + return NULL; + + upper = list_first_entry(&dev->adj_list.upper, + struct netdev_adjacent, list); + if (likely(upper->master) && !upper->ignore) + return upper->dev; + return NULL; +} + /** * netdev_has_any_lower_dev - Check if device is linked to some device * @dev: device @@ -6644,6 +6582,23 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, } EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu); +static struct net_device *__netdev_next_upper_dev(struct net_device *dev, + struct list_head **iter, + bool *ignore) +{ + struct netdev_adjacent *upper; + + upper = list_entry((*iter)->next, struct netdev_adjacent, list); + + if (&upper->list == &dev->adj_list.upper) + return NULL; + + *iter = &upper->list; + *ignore = upper->ignore; + + return upper->dev; +} + static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev, struct list_head **iter) { @@ -6661,34 +6616,111 @@ static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev, return upper->dev; } +static int __netdev_walk_all_upper_dev(struct net_device *dev, + int (*fn)(struct net_device *dev, + void *data), + void *data) +{ + struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1]; + struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1]; + int ret, cur = 0; + bool ignore; + + now = dev; + iter = &dev->adj_list.upper; + + while (1) { + if (now != dev) { + ret = fn(now, data); + if (ret) + return ret; + } + + next = NULL; + while (1) { + udev = __netdev_next_upper_dev(now, &iter, &ignore); + if (!udev) + break; + if (ignore) + continue; + + next = udev; + niter = &udev->adj_list.upper; + dev_stack[cur] = now; + iter_stack[cur++] = iter; + break; + } + + if (!next) { + if (!cur) + return 0; + next = dev_stack[--cur]; + niter = iter_stack[cur]; + } + + now = next; + iter = niter; + } + + return 0; +} + int netdev_walk_all_upper_dev_rcu(struct net_device *dev, int (*fn)(struct net_device *dev, void *data), void *data) { - struct net_device *udev; - struct list_head *iter; - int ret; + struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1]; + struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1]; + int ret, cur = 0; - for (iter = &dev->adj_list.upper, - udev = netdev_next_upper_dev_rcu(dev, &iter); - udev; - udev = netdev_next_upper_dev_rcu(dev, &iter)) { - /* first is the upper device itself */ - ret = fn(udev, data); - if (ret) - return ret; + now = dev; + iter = &dev->adj_list.upper; - /* then look at all of its upper devices */ - ret = netdev_walk_all_upper_dev_rcu(udev, fn, data); - if (ret) - return ret; + while (1) { + if (now != dev) { + ret = fn(now, data); + if (ret) + return ret; + } + + next = NULL; + while (1) { + udev = netdev_next_upper_dev_rcu(now, &iter); + if (!udev) + break; + + next = udev; + niter = &udev->adj_list.upper; + dev_stack[cur] = now; + iter_stack[cur++] = iter; + break; + } + + if (!next) { + if (!cur) + return 0; + next = dev_stack[--cur]; + niter = iter_stack[cur]; + } + + now = next; + iter = niter; } return 0; } EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu); +static bool __netdev_has_upper_dev(struct net_device *dev, + struct net_device *upper_dev) +{ + ASSERT_RTNL(); + + return __netdev_walk_all_upper_dev(dev, ____netdev_has_upper_dev, + upper_dev); +} + /** * netdev_lower_get_next_private - Get the next ->private from the * lower neighbour list @@ -6785,34 +6817,119 @@ static struct net_device *netdev_next_lower_dev(struct net_device *dev, return lower->dev; } +static struct net_device *__netdev_next_lower_dev(struct net_device *dev, + struct list_head **iter, + bool *ignore) +{ + struct netdev_adjacent *lower; + + lower = list_entry((*iter)->next, struct netdev_adjacent, list); + + if (&lower->list == &dev->adj_list.lower) + return NULL; + + *iter = &lower->list; + *ignore = lower->ignore; + + return lower->dev; +} + int netdev_walk_all_lower_dev(struct net_device *dev, int (*fn)(struct net_device *dev, void *data), void *data) { - struct net_device *ldev; - struct list_head *iter; - int ret; + struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1]; + struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1]; + int ret, cur = 0; - for (iter = &dev->adj_list.lower, - ldev = netdev_next_lower_dev(dev, &iter); - ldev; - ldev = netdev_next_lower_dev(dev, &iter)) { - /* first is the lower device itself */ - ret = fn(ldev, data); - if (ret) - return ret; + now = dev; + iter = &dev->adj_list.lower; - /* then look at all of its lower devices */ - ret = netdev_walk_all_lower_dev(ldev, fn, data); - if (ret) - return ret; + while (1) { + if (now != dev) { + ret = fn(now, data); + if (ret) + return ret; + } + + next = NULL; + while (1) { + ldev = netdev_next_lower_dev(now, &iter); + if (!ldev) + break; + + next = ldev; + niter = &ldev->adj_list.lower; + dev_stack[cur] = now; + iter_stack[cur++] = iter; + break; + } + + if (!next) { + if (!cur) + return 0; + next = dev_stack[--cur]; + niter = iter_stack[cur]; + } + + now = next; + iter = niter; } return 0; } EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev); +static int __netdev_walk_all_lower_dev(struct net_device *dev, + int (*fn)(struct net_device *dev, + void *data), + void *data) +{ + struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1]; + struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1]; + int ret, cur = 0; + bool ignore; + + now = dev; + iter = &dev->adj_list.lower; + + while (1) { + if (now != dev) { + ret = fn(now, data); + if (ret) + return ret; + } + + next = NULL; + while (1) { + ldev = __netdev_next_lower_dev(now, &iter, &ignore); + if (!ldev) + break; + if (ignore) + continue; + + next = ldev; + niter = &ldev->adj_list.lower; + dev_stack[cur] = now; + iter_stack[cur++] = iter; + break; + } + + if (!next) { + if (!cur) + return 0; + next = dev_stack[--cur]; + niter = iter_stack[cur]; + } + + now = next; + iter = niter; + } + + return 0; +} + static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev, struct list_head **iter) { @@ -6827,28 +6944,99 @@ static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev, return lower->dev; } -int netdev_walk_all_lower_dev_rcu(struct net_device *dev, - int (*fn)(struct net_device *dev, - void *data), - void *data) +static u8 __netdev_upper_depth(struct net_device *dev) +{ + struct net_device *udev; + struct list_head *iter; + u8 max_depth = 0; + bool ignore; + + for (iter = &dev->adj_list.upper, + udev = __netdev_next_upper_dev(dev, &iter, &ignore); + udev; + udev = __netdev_next_upper_dev(dev, &iter, &ignore)) { + if (ignore) + continue; + if (max_depth < udev->upper_level) + max_depth = udev->upper_level; + } + + return max_depth; +} + +static u8 __netdev_lower_depth(struct net_device *dev) { struct net_device *ldev; struct list_head *iter; - int ret; + u8 max_depth = 0; + bool ignore; for (iter = &dev->adj_list.lower, - ldev = netdev_next_lower_dev_rcu(dev, &iter); + ldev = __netdev_next_lower_dev(dev, &iter, &ignore); ldev; - ldev = netdev_next_lower_dev_rcu(dev, &iter)) { - /* first is the lower device itself */ - ret = fn(ldev, data); - if (ret) - return ret; + ldev = __netdev_next_lower_dev(dev, &iter, &ignore)) { + if (ignore) + continue; + if (max_depth < ldev->lower_level) + max_depth = ldev->lower_level; + } - /* then look at all of its lower devices */ - ret = netdev_walk_all_lower_dev_rcu(ldev, fn, data); - if (ret) - return ret; + return max_depth; +} + +static int __netdev_update_upper_level(struct net_device *dev, void *data) +{ + dev->upper_level = __netdev_upper_depth(dev) + 1; + return 0; +} + +static int __netdev_update_lower_level(struct net_device *dev, void *data) +{ + dev->lower_level = __netdev_lower_depth(dev) + 1; + return 0; +} + +int netdev_walk_all_lower_dev_rcu(struct net_device *dev, + int (*fn)(struct net_device *dev, + void *data), + void *data) +{ + struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1]; + struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1]; + int ret, cur = 0; + + now = dev; + iter = &dev->adj_list.lower; + + while (1) { + if (now != dev) { + ret = fn(now, data); + if (ret) + return ret; + } + + next = NULL; + while (1) { + ldev = netdev_next_lower_dev_rcu(now, &iter); + if (!ldev) + break; + + next = ldev; + niter = &ldev->adj_list.lower; + dev_stack[cur] = now; + iter_stack[cur++] = iter; + break; + } + + if (!next) { + if (!cur) + return 0; + next = dev_stack[--cur]; + niter = iter_stack[cur]; + } + + now = next; + iter = niter; } return 0; @@ -6952,6 +7140,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, adj->master = master; adj->ref_nr = 1; adj->private = private; + adj->ignore = false; dev_hold(adj_dev); pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n", @@ -7102,14 +7291,17 @@ static int __netdev_upper_dev_link(struct net_device *dev, return -EBUSY; /* To prevent loops, check if dev is not upper device to upper_dev. */ - if (netdev_has_upper_dev(upper_dev, dev)) + if (__netdev_has_upper_dev(upper_dev, dev)) return -EBUSY; + if ((dev->lower_level + upper_dev->upper_level) > MAX_NEST_DEV) + return -EMLINK; + if (!master) { - if (netdev_has_upper_dev(dev, upper_dev)) + if (__netdev_has_upper_dev(dev, upper_dev)) return -EEXIST; } else { - master_dev = netdev_master_upper_dev_get(dev); + master_dev = __netdev_master_upper_dev_get(dev); if (master_dev) return master_dev == upper_dev ? -EEXIST : -EBUSY; } @@ -7131,6 +7323,13 @@ static int __netdev_upper_dev_link(struct net_device *dev, if (ret) goto rollback; + __netdev_update_upper_level(dev, NULL); + __netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL); + + __netdev_update_lower_level(upper_dev, NULL); + __netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, + NULL); + return 0; rollback: @@ -7213,9 +7412,96 @@ void netdev_upper_dev_unlink(struct net_device *dev, call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); + + __netdev_update_upper_level(dev, NULL); + __netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL); + + __netdev_update_lower_level(upper_dev, NULL); + __netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level, + NULL); } EXPORT_SYMBOL(netdev_upper_dev_unlink); +static void __netdev_adjacent_dev_set(struct net_device *upper_dev, + struct net_device *lower_dev, + bool val) +{ + struct netdev_adjacent *adj; + + adj = __netdev_find_adj(lower_dev, &upper_dev->adj_list.lower); + if (adj) + adj->ignore = val; + + adj = __netdev_find_adj(upper_dev, &lower_dev->adj_list.upper); + if (adj) + adj->ignore = val; +} + +static void netdev_adjacent_dev_disable(struct net_device *upper_dev, + struct net_device *lower_dev) +{ + __netdev_adjacent_dev_set(upper_dev, lower_dev, true); +} + +static void netdev_adjacent_dev_enable(struct net_device *upper_dev, + struct net_device *lower_dev) +{ + __netdev_adjacent_dev_set(upper_dev, lower_dev, false); +} + +int netdev_adjacent_change_prepare(struct net_device *old_dev, + struct net_device *new_dev, + struct net_device *dev, + struct netlink_ext_ack *extack) +{ + int err; + + if (!new_dev) + return 0; + + if (old_dev && new_dev != old_dev) + netdev_adjacent_dev_disable(dev, old_dev); + + err = netdev_upper_dev_link(new_dev, dev, extack); + if (err) { + if (old_dev && new_dev != old_dev) + netdev_adjacent_dev_enable(dev, old_dev); + return err; + } + + return 0; +} +EXPORT_SYMBOL(netdev_adjacent_change_prepare); + +void netdev_adjacent_change_commit(struct net_device *old_dev, + struct net_device *new_dev, + struct net_device *dev) +{ + if (!new_dev || !old_dev) + return; + + if (new_dev == old_dev) + return; + + netdev_adjacent_dev_enable(dev, old_dev); + netdev_upper_dev_unlink(old_dev, dev); +} +EXPORT_SYMBOL(netdev_adjacent_change_commit); + +void netdev_adjacent_change_abort(struct net_device *old_dev, + struct net_device *new_dev, + struct net_device *dev) +{ + if (!new_dev) + return; + + if (old_dev && new_dev != old_dev) + netdev_adjacent_dev_enable(dev, old_dev); + + netdev_upper_dev_unlink(new_dev, dev); +} +EXPORT_SYMBOL(netdev_adjacent_change_abort); + /** * netdev_bonding_info_change - Dispatch event about slave change * @dev: device @@ -7329,25 +7615,6 @@ void *netdev_lower_dev_get_private(struct net_device *dev, EXPORT_SYMBOL(netdev_lower_dev_get_private); -int dev_get_nest_level(struct net_device *dev) -{ - struct net_device *lower = NULL; - struct list_head *iter; - int max_nest = -1; - int nest; - - ASSERT_RTNL(); - - netdev_for_each_lower_dev(dev, lower, iter) { - nest = dev_get_nest_level(lower); - if (max_nest < nest) - max_nest = nest; - } - - return max_nest + 1; -} -EXPORT_SYMBOL(dev_get_nest_level); - /** * netdev_lower_change - Dispatch event about lower device state change * @lower_dev: device @@ -8154,7 +8421,8 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, return -EINVAL; } - if (prog->aux->id == prog_id) { + /* prog->aux->id may be 0 for orphaned device-bound progs */ + if (prog->aux->id && prog->aux->id == prog_id) { bpf_prog_put(prog); return 0; } @@ -8619,7 +8887,7 @@ static void netdev_init_one_queue(struct net_device *dev, { /* Initialize queue lock */ spin_lock_init(&queue->_xmit_lock); - netdev_set_xmit_lockdep_class(&queue->_xmit_lock, dev->type); + lockdep_set_class(&queue->_xmit_lock, &dev->qdisc_xmit_lock_key); queue->xmit_lock_owner = -1; netdev_queue_numa_node_write(queue, NUMA_NO_NODE); queue->dev = dev; @@ -8666,6 +8934,43 @@ void netif_tx_stop_all_queues(struct net_device *dev) } EXPORT_SYMBOL(netif_tx_stop_all_queues); +static void netdev_register_lockdep_key(struct net_device *dev) +{ + lockdep_register_key(&dev->qdisc_tx_busylock_key); + lockdep_register_key(&dev->qdisc_running_key); + lockdep_register_key(&dev->qdisc_xmit_lock_key); + lockdep_register_key(&dev->addr_list_lock_key); +} + +static void netdev_unregister_lockdep_key(struct net_device *dev) +{ + lockdep_unregister_key(&dev->qdisc_tx_busylock_key); + lockdep_unregister_key(&dev->qdisc_running_key); + lockdep_unregister_key(&dev->qdisc_xmit_lock_key); + lockdep_unregister_key(&dev->addr_list_lock_key); +} + +void netdev_update_lockdep_key(struct net_device *dev) +{ + struct netdev_queue *queue; + int i; + + lockdep_unregister_key(&dev->qdisc_xmit_lock_key); + lockdep_unregister_key(&dev->addr_list_lock_key); + + lockdep_register_key(&dev->qdisc_xmit_lock_key); + lockdep_register_key(&dev->addr_list_lock_key); + + lockdep_set_class(&dev->addr_list_lock, &dev->addr_list_lock_key); + for (i = 0; i < dev->num_tx_queues; i++) { + queue = netdev_get_tx_queue(dev, i); + + lockdep_set_class(&queue->_xmit_lock, + &dev->qdisc_xmit_lock_key); + } +} +EXPORT_SYMBOL(netdev_update_lockdep_key); + /** * register_netdevice - register a network device * @dev: device to register @@ -8700,7 +9005,7 @@ int register_netdevice(struct net_device *dev) BUG_ON(!net); spin_lock_init(&dev->addr_list_lock); - netdev_set_addr_lockdep_class(dev); + lockdep_set_class(&dev->addr_list_lock, &dev->addr_list_lock_key); ret = dev_get_valid_name(net, dev, dev->name); if (ret < 0) @@ -9210,8 +9515,12 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev_net_set(dev, &init_net); + netdev_register_lockdep_key(dev); + dev->gso_max_size = GSO_MAX_SIZE; dev->gso_max_segs = GSO_MAX_SEGS; + dev->upper_level = 1; + dev->lower_level = 1; INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); @@ -9292,6 +9601,8 @@ void free_netdev(struct net_device *dev) free_percpu(dev->pcpu_refcnt); dev->pcpu_refcnt = NULL; + netdev_unregister_lockdep_key(dev); + /* Compatibility with error handling in drivers */ if (dev->reg_state == NETREG_UNINITIALIZED) { netdev_freemem(dev); @@ -9460,7 +9771,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char call_netdevice_notifiers(NETDEV_UNREGISTER, dev); rcu_barrier(); - new_nsid = peernet2id_alloc(dev_net(dev), net); + new_nsid = peernet2id_alloc(dev_net(dev), net, GFP_KERNEL); /* If there is an ifindex conflict assign a new one */ if (__dev_get_by_index(net, dev->ifindex)) new_ifindex = dev_new_index(net); diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 6393ba930097b49b26a70cf01b657da08514f552..2f949b5a1eb9cd9a65e0c0a6d089032a92e100e2 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -637,7 +637,7 @@ int dev_uc_sync(struct net_device *to, struct net_device *from) if (to->addr_len != from->addr_len) return -EINVAL; - netif_addr_lock_nested(to); + netif_addr_lock(to); err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); if (!err) __dev_set_rx_mode(to); @@ -667,7 +667,7 @@ int dev_uc_sync_multiple(struct net_device *to, struct net_device *from) if (to->addr_len != from->addr_len) return -EINVAL; - netif_addr_lock_nested(to); + netif_addr_lock(to); err = __hw_addr_sync_multiple(&to->uc, &from->uc, to->addr_len); if (!err) __dev_set_rx_mode(to); @@ -691,7 +691,7 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from) return; netif_addr_lock_bh(from); - netif_addr_lock_nested(to); + netif_addr_lock(to); __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -858,7 +858,7 @@ int dev_mc_sync(struct net_device *to, struct net_device *from) if (to->addr_len != from->addr_len) return -EINVAL; - netif_addr_lock_nested(to); + netif_addr_lock(to); err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); if (!err) __dev_set_rx_mode(to); @@ -888,7 +888,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from) if (to->addr_len != from->addr_len) return -EINVAL; - netif_addr_lock_nested(to); + netif_addr_lock(to); err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len); if (!err) __dev_set_rx_mode(to); @@ -912,7 +912,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from) return; netif_addr_lock_bh(from); - netif_addr_lock_nested(to); + netif_addr_lock(to); __hw_addr_unsync(&to->mc, &from->mc, to->addr_len); __dev_set_rx_mode(to); netif_addr_unlock(to); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index c763106c73fc5d660e8489da0f0823e0536fd96e..cd9bc67381b221aae31695f15dec0784973c5da9 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1396,11 +1396,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr) static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) { - struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; + struct ethtool_wolinfo wol; if (!dev->ethtool_ops->get_wol) return -EOPNOTSUPP; + memset(&wol, 0, sizeof(struct ethtool_wolinfo)); + wol.cmd = ETHTOOL_GWOL; dev->ethtool_ops->get_wol(dev, &wol); if (copy_to_user(useraddr, &wol, sizeof(wol))) diff --git a/net/core/filter.c b/net/core/filter.c index ed6563622ce31dcced4e6ba622770e26f1f7756a..3fed5755494bd39cf55ca1806ead67609ae8b587 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4252,12 +4252,14 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock, case SO_RCVBUF: val = min_t(u32, val, sysctl_rmem_max); sk->sk_userlocks |= SOCK_RCVBUF_LOCK; - sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); + WRITE_ONCE(sk->sk_rcvbuf, + max_t(int, val * 2, SOCK_MIN_RCVBUF)); break; case SO_SNDBUF: val = min_t(u32, val, sysctl_wmem_max); sk->sk_userlocks |= SOCK_SNDBUF_LOCK; - sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); + WRITE_ONCE(sk->sk_sndbuf, + max_t(int, val * 2, SOCK_MIN_SNDBUF)); break; case SO_MAX_PACING_RATE: /* 32bit version */ if (val != ~0U) @@ -4274,7 +4276,7 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock, case SO_RCVLOWAT: if (val < 0) val = INT_MAX; - sk->sk_rcvlowat = val ? : 1; + WRITE_ONCE(sk->sk_rcvlowat, val ? : 1); break; case SO_MARK: if (sk->sk_mark != val) { diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 7c09d87d3269e4d01fd895c595a3a6e67d350685..68eda10d0680749ef07372951debab913449e661 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1350,30 +1350,21 @@ bool __skb_flow_dissect(const struct net *net, } EXPORT_SYMBOL(__skb_flow_dissect); -static u32 hashrnd __read_mostly; +static siphash_key_t hashrnd __read_mostly; static __always_inline void __flow_hash_secret_init(void) { net_get_random_once(&hashrnd, sizeof(hashrnd)); } -static __always_inline u32 __flow_hash_words(const u32 *words, u32 length, - u32 keyval) +static const void *flow_keys_hash_start(const struct flow_keys *flow) { - return jhash2(words, length, keyval); -} - -static inline const u32 *flow_keys_hash_start(const struct flow_keys *flow) -{ - const void *p = flow; - - BUILD_BUG_ON(FLOW_KEYS_HASH_OFFSET % sizeof(u32)); - return (const u32 *)(p + FLOW_KEYS_HASH_OFFSET); + BUILD_BUG_ON(FLOW_KEYS_HASH_OFFSET % SIPHASH_ALIGNMENT); + return &flow->FLOW_KEYS_HASH_START_FIELD; } static inline size_t flow_keys_hash_length(const struct flow_keys *flow) { size_t diff = FLOW_KEYS_HASH_OFFSET + sizeof(flow->addrs); - BUILD_BUG_ON((sizeof(*flow) - FLOW_KEYS_HASH_OFFSET) % sizeof(u32)); BUILD_BUG_ON(offsetof(typeof(*flow), addrs) != sizeof(*flow) - sizeof(flow->addrs)); @@ -1388,7 +1379,7 @@ static inline size_t flow_keys_hash_length(const struct flow_keys *flow) diff -= sizeof(flow->addrs.tipckey); break; } - return (sizeof(*flow) - diff) / sizeof(u32); + return sizeof(*flow) - diff; } __be32 flow_get_u32_src(const struct flow_keys *flow) @@ -1454,14 +1445,15 @@ static inline void __flow_hash_consistentify(struct flow_keys *keys) } } -static inline u32 __flow_hash_from_keys(struct flow_keys *keys, u32 keyval) +static inline u32 __flow_hash_from_keys(struct flow_keys *keys, + const siphash_key_t *keyval) { u32 hash; __flow_hash_consistentify(keys); - hash = __flow_hash_words(flow_keys_hash_start(keys), - flow_keys_hash_length(keys), keyval); + hash = siphash(flow_keys_hash_start(keys), + flow_keys_hash_length(keys), keyval); if (!hash) hash = 1; @@ -1471,12 +1463,13 @@ static inline u32 __flow_hash_from_keys(struct flow_keys *keys, u32 keyval) u32 flow_hash_from_keys(struct flow_keys *keys) { __flow_hash_secret_init(); - return __flow_hash_from_keys(keys, hashrnd); + return __flow_hash_from_keys(keys, &hashrnd); } EXPORT_SYMBOL(flow_hash_from_keys); static inline u32 ___skb_get_hash(const struct sk_buff *skb, - struct flow_keys *keys, u32 keyval) + struct flow_keys *keys, + const siphash_key_t *keyval) { skb_flow_dissect_flow_keys(skb, keys, FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); @@ -1524,7 +1517,7 @@ u32 __skb_get_hash_symmetric(const struct sk_buff *skb) &keys, NULL, 0, 0, 0, FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); - return __flow_hash_from_keys(&keys, hashrnd); + return __flow_hash_from_keys(&keys, &hashrnd); } EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric); @@ -1544,13 +1537,14 @@ void __skb_get_hash(struct sk_buff *skb) __flow_hash_secret_init(); - hash = ___skb_get_hash(skb, &keys, hashrnd); + hash = ___skb_get_hash(skb, &keys, &hashrnd); __skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys)); } EXPORT_SYMBOL(__skb_get_hash); -__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb) +__u32 skb_get_hash_perturb(const struct sk_buff *skb, + const siphash_key_t *perturb) { struct flow_keys keys; diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c index f93785e5833c1f82eed0176e3f939b32216dbaab..74cfb8b5ab3306485385e3e5682350fe9a0709dc 100644 --- a/net/core/lwt_bpf.c +++ b/net/core/lwt_bpf.c @@ -88,11 +88,16 @@ static int bpf_lwt_input_reroute(struct sk_buff *skb) int err = -EINVAL; if (skb->protocol == htons(ETH_P_IP)) { + struct net_device *dev = skb_dst(skb)->dev; struct iphdr *iph = ip_hdr(skb); + dev_hold(dev); + skb_dst_drop(skb); err = ip_route_input_noref(skb, iph->daddr, iph->saddr, - iph->tos, skb_dst(skb)->dev); + iph->tos, dev); + dev_put(dev); } else if (skb->protocol == htons(ETH_P_IPV6)) { + skb_dst_drop(skb); err = ipv6_stub->ipv6_route_input(skb); } else { err = -EAFNOSUPPORT; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index a0e0d298c9918f55afe34264c63d0f791160c898..39402840025e18682da44f40c509b265f9743fd1 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -245,11 +245,12 @@ static int __peernet2id(struct net *net, struct net *peer) return __peernet2id_alloc(net, peer, &no); } -static void rtnl_net_notifyid(struct net *net, int cmd, int id); +static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid, + struct nlmsghdr *nlh, gfp_t gfp); /* This function returns the id of a peer netns. If no id is assigned, one will * be allocated and returned. */ -int peernet2id_alloc(struct net *net, struct net *peer) +int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp) { bool alloc = false, alive = false; int id; @@ -268,7 +269,7 @@ int peernet2id_alloc(struct net *net, struct net *peer) id = __peernet2id_alloc(net, peer, &alloc); spin_unlock_bh(&net->nsid_lock); if (alloc && id >= 0) - rtnl_net_notifyid(net, RTM_NEWNSID, id); + rtnl_net_notifyid(net, RTM_NEWNSID, id, 0, NULL, gfp); if (alive) put_net(peer); return id; @@ -478,6 +479,7 @@ struct net *copy_net_ns(unsigned long flags, if (rv < 0) { put_userns: + key_remove_domain(net->key_domain); put_user_ns(user_ns); net_drop_ns(net); dec_ucounts: @@ -532,7 +534,8 @@ static void unhash_nsid(struct net *net, struct net *last) idr_remove(&tmp->netns_ids, id); spin_unlock_bh(&tmp->nsid_lock); if (id >= 0) - rtnl_net_notifyid(tmp, RTM_DELNSID, id); + rtnl_net_notifyid(tmp, RTM_DELNSID, id, 0, NULL, + GFP_KERNEL); if (tmp == last) break; } @@ -764,7 +767,8 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh, err = alloc_netid(net, peer, nsid); spin_unlock_bh(&net->nsid_lock); if (err >= 0) { - rtnl_net_notifyid(net, RTM_NEWNSID, err); + rtnl_net_notifyid(net, RTM_NEWNSID, err, NETLINK_CB(skb).portid, + nlh, GFP_KERNEL); err = 0; } else if (err == -ENOSPC && nsid >= 0) { err = -EEXIST; @@ -1051,16 +1055,19 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb) return err < 0 ? err : skb->len; } -static void rtnl_net_notifyid(struct net *net, int cmd, int id) +static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid, + struct nlmsghdr *nlh, gfp_t gfp) { struct net_fill_args fillargs = { + .portid = portid, + .seq = nlh ? nlh->nlmsg_seq : 0, .cmd = cmd, .nsid = id, }; struct sk_buff *msg; int err = -ENOMEM; - msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL); + msg = nlmsg_new(rtnl_net_get_size(), gfp); if (!msg) goto out; @@ -1068,7 +1075,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id) if (err < 0) goto err_out; - rtnl_notify(msg, net, 0, RTNLGRP_NSID, NULL, 0); + rtnl_notify(msg, net, portid, RTNLGRP_NSID, nlh, gfp); return; err_out: diff --git a/net/core/request_sock.c b/net/core/request_sock.c index c9bb00008528414486bb58ba4c26b003545c6ae4..f35c2e9984062ba4bed637eaeace4eb9e71dadc0 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -96,7 +96,7 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, fastopenq = &inet_csk(lsk)->icsk_accept_queue.fastopenq; - tcp_sk(sk)->fastopen_rsk = NULL; + RCU_INIT_POINTER(tcp_sk(sk)->fastopen_rsk, NULL); spin_lock_bh(&fastopenq->lock); fastopenq->qlen--; tcp_rsk(req)->tfo_listener = false; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1ee6460f82756be6dd797b000c11f29826e2e710..c81cd80114d993ad1d924c3e388813474c211904 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1523,7 +1523,7 @@ static noinline_for_stack int nla_put_ifalias(struct sk_buff *skb, static int rtnl_fill_link_netnsid(struct sk_buff *skb, const struct net_device *dev, - struct net *src_net) + struct net *src_net, gfp_t gfp) { bool put_iflink = false; @@ -1531,7 +1531,7 @@ static int rtnl_fill_link_netnsid(struct sk_buff *skb, struct net *link_net = dev->rtnl_link_ops->get_link_net(dev); if (!net_eq(dev_net(dev), link_net)) { - int id = peernet2id_alloc(src_net, link_net); + int id = peernet2id_alloc(src_net, link_net, gfp); if (nla_put_s32(skb, IFLA_LINK_NETNSID, id)) return -EMSGSIZE; @@ -1589,7 +1589,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, int type, u32 pid, u32 seq, u32 change, unsigned int flags, u32 ext_filter_mask, u32 event, int *new_nsid, int new_ifindex, - int tgt_netnsid) + int tgt_netnsid, gfp_t gfp) { struct ifinfomsg *ifm; struct nlmsghdr *nlh; @@ -1681,7 +1681,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, goto nla_put_failure; } - if (rtnl_fill_link_netnsid(skb, dev, src_net)) + if (rtnl_fill_link_netnsid(skb, dev, src_net, gfp)) goto nla_put_failure; if (new_nsid && @@ -2001,7 +2001,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) NETLINK_CB(cb->skb).portid, nlh->nlmsg_seq, 0, flags, ext_filter_mask, 0, NULL, 0, - netnsid); + netnsid, GFP_KERNEL); if (err < 0) { if (likely(skb->len)) @@ -2355,6 +2355,7 @@ static int do_set_master(struct net_device *dev, int ifindex, err = ops->ndo_del_slave(upper_dev, dev); if (err) return err; + netdev_update_lockdep_key(dev); } else { return -EOPNOTSUPP; } @@ -3359,7 +3360,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh, err = rtnl_fill_ifinfo(nskb, dev, net, RTM_NEWLINK, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0, 0, ext_filter_mask, - 0, NULL, 0, netnsid); + 0, NULL, 0, netnsid, GFP_KERNEL); if (err < 0) { /* -EMSGSIZE implies BUG in if_nlmsg_size */ WARN_ON(err == -EMSGSIZE); @@ -3471,7 +3472,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev, err = rtnl_fill_ifinfo(skb, dev, dev_net(dev), type, 0, 0, change, 0, 0, event, - new_nsid, new_ifindex, -1); + new_nsid, new_ifindex, -1, flags); if (err < 0) { /* -EMSGSIZE implies BUG in if_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); @@ -3916,7 +3917,7 @@ static int valid_fdb_dump_strict(const struct nlmsghdr *nlh, ndm = nlmsg_data(nlh); if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_state || ndm->ndm_flags || ndm->ndm_type) { - NL_SET_ERR_MSG(extack, "Invalid values in header for fbd dump request"); + NL_SET_ERR_MSG(extack, "Invalid values in header for fdb dump request"); return -EINVAL; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 529133611ea2947b1b1af51394756b7797f8cde3..867e61df00dbc18efcb6251600a04f9ddb12bd92 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4415,7 +4415,7 @@ static void skb_set_err_queue(struct sk_buff *skb) int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) { if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= - (unsigned int)sk->sk_rcvbuf) + (unsigned int)READ_ONCE(sk->sk_rcvbuf)) return -ENOMEM; skb_orphan(skb); @@ -5477,12 +5477,14 @@ static void skb_mod_eth_type(struct sk_buff *skb, struct ethhdr *hdr, * @skb: buffer * @mpls_lse: MPLS label stack entry to push * @mpls_proto: ethertype of the new MPLS header (expects 0x8847 or 0x8848) + * @mac_len: length of the MAC header * * Expects skb->data at mac header. * * Returns 0 on success, -errno otherwise. */ -int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto) +int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, + int mac_len) { struct mpls_shim_hdr *lse; int err; @@ -5499,15 +5501,15 @@ int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto) return err; if (!skb->inner_protocol) { - skb_set_inner_network_header(skb, skb->mac_len); + skb_set_inner_network_header(skb, mac_len); skb_set_inner_protocol(skb, skb->protocol); } skb_push(skb, MPLS_HLEN); memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb), - skb->mac_len); + mac_len); skb_reset_mac_header(skb); - skb_set_network_header(skb, skb->mac_len); + skb_set_network_header(skb, mac_len); lse = mpls_hdr(skb); lse->label_stack_entry = mpls_lse; @@ -5526,29 +5528,30 @@ EXPORT_SYMBOL_GPL(skb_mpls_push); * * @skb: buffer * @next_proto: ethertype of header after popped MPLS header + * @mac_len: length of the MAC header * * Expects skb->data at mac header. * * Returns 0 on success, -errno otherwise. */ -int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto) +int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len) { int err; if (unlikely(!eth_p_mpls(skb->protocol))) - return -EINVAL; + return 0; - err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN); + err = skb_ensure_writable(skb, mac_len + MPLS_HLEN); if (unlikely(err)) return err; skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN); memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb), - skb->mac_len); + mac_len); __skb_pull(skb, MPLS_HLEN); skb_reset_mac_header(skb); - skb_set_network_header(skb, skb->mac_len); + skb_set_network_header(skb, mac_len); if (skb->dev && skb->dev->type == ARPHRD_ETHER) { struct ethhdr *hdr; diff --git a/net/core/sock.c b/net/core/sock.c index fac2b4d80de5e54c77628073d7930bddf8a10cb3..ac78a570e43add1ce263841212b3759dbbfd8eae 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -522,7 +522,7 @@ int __sk_receive_skb(struct sock *sk, struct sk_buff *skb, rc = sk_backlog_rcv(sk, skb); mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); - } else if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) { + } else if (sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf))) { bh_unlock_sock(sk); atomic_inc(&sk->sk_drops); goto discard_and_relse; @@ -785,7 +785,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname, */ val = min_t(int, val, INT_MAX / 2); sk->sk_userlocks |= SOCK_SNDBUF_LOCK; - sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); + WRITE_ONCE(sk->sk_sndbuf, + max_t(int, val * 2, SOCK_MIN_SNDBUF)); /* Wake up sending tasks if we upped the value. */ sk->sk_write_space(sk); break; @@ -831,7 +832,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname, * returning the value we actually used in getsockopt * is the most desirable behavior. */ - sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); + WRITE_ONCE(sk->sk_rcvbuf, + max_t(int, val * 2, SOCK_MIN_RCVBUF)); break; case SO_RCVBUFFORCE: @@ -974,7 +976,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, if (sock->ops->set_rcvlowat) ret = sock->ops->set_rcvlowat(sk, val); else - sk->sk_rcvlowat = val ? : 1; + WRITE_ONCE(sk->sk_rcvlowat, val ? : 1); break; case SO_RCVTIMEO_OLD: @@ -1125,7 +1127,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, break; } case SO_INCOMING_CPU: - sk->sk_incoming_cpu = val; + WRITE_ONCE(sk->sk_incoming_cpu, val); break; case SO_CNX_ADVICE: @@ -1474,7 +1476,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; case SO_INCOMING_CPU: - v.val = sk->sk_incoming_cpu; + v.val = READ_ONCE(sk->sk_incoming_cpu); break; case SO_MEMINFO: @@ -2088,8 +2090,10 @@ EXPORT_SYMBOL(sock_i_ino); struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, gfp_t priority) { - if (force || refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { + if (force || + refcount_read(&sk->sk_wmem_alloc) < READ_ONCE(sk->sk_sndbuf)) { struct sk_buff *skb = alloc_skb(size, priority); + if (skb) { skb_set_owner_w(skb, sk); return skb; @@ -2190,7 +2194,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo) break; set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); - if (refcount_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) + if (refcount_read(&sk->sk_wmem_alloc) < READ_ONCE(sk->sk_sndbuf)) break; if (sk->sk_shutdown & SEND_SHUTDOWN) break; @@ -2225,7 +2229,7 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, if (sk->sk_shutdown & SEND_SHUTDOWN) goto failure; - if (sk_wmem_alloc_get(sk) < sk->sk_sndbuf) + if (sk_wmem_alloc_get(sk) < READ_ONCE(sk->sk_sndbuf)) break; sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); @@ -2334,8 +2338,8 @@ static void sk_leave_memory_pressure(struct sock *sk) } else { unsigned long *memory_pressure = sk->sk_prot->memory_pressure; - if (memory_pressure && *memory_pressure) - *memory_pressure = 0; + if (memory_pressure && READ_ONCE(*memory_pressure)) + WRITE_ONCE(*memory_pressure, 0); } } @@ -2806,7 +2810,7 @@ static void sock_def_write_space(struct sock *sk) /* Do not wake up a writer until he can make "significant" * progress. --DaveM */ - if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { + if ((refcount_read(&sk->sk_wmem_alloc) << 1) <= READ_ONCE(sk->sk_sndbuf)) { wq = rcu_dereference(sk->sk_wq); if (skwq_has_sleeper(wq)) wake_up_interruptible_sync_poll(&wq->wait, EPOLLOUT | @@ -3204,13 +3208,13 @@ void sk_get_meminfo(const struct sock *sk, u32 *mem) memset(mem, 0, sizeof(*mem) * SK_MEMINFO_VARS); mem[SK_MEMINFO_RMEM_ALLOC] = sk_rmem_alloc_get(sk); - mem[SK_MEMINFO_RCVBUF] = sk->sk_rcvbuf; + mem[SK_MEMINFO_RCVBUF] = READ_ONCE(sk->sk_rcvbuf); mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk); - mem[SK_MEMINFO_SNDBUF] = sk->sk_sndbuf; + mem[SK_MEMINFO_SNDBUF] = READ_ONCE(sk->sk_sndbuf); mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc; - mem[SK_MEMINFO_WMEM_QUEUED] = sk->sk_wmem_queued; + mem[SK_MEMINFO_WMEM_QUEUED] = READ_ONCE(sk->sk_wmem_queued); mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc); - mem[SK_MEMINFO_BACKLOG] = sk->sk_backlog.len; + mem[SK_MEMINFO_BACKLOG] = READ_ONCE(sk->sk_backlog.len); mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops); } @@ -3596,7 +3600,7 @@ bool sk_busy_loop_end(void *p, unsigned long start_time) { struct sock *sk = p; - return !skb_queue_empty(&sk->sk_receive_queue) || + return !skb_queue_empty_lockless(&sk->sk_receive_queue) || sk_busy_loop_timeout(sk, start_time); } EXPORT_SYMBOL(sk_busy_loop_end); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index d9b4200ed12df8ecc7ff7de26827207c5a290e37..0d8f782c25ccc031e5322beccb0242ee42b032b9 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -117,7 +117,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) inet->inet_daddr, inet->inet_sport, inet->inet_dport); - inet->inet_id = dp->dccps_iss ^ jiffies; + inet->inet_id = prandom_u32(); err = dccp_connect(sk); rt = NULL; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 0ea75286abf46ad9da2e6c58d4facc91f731b8bf..3349ea81f9016fb785ec888fadf86faa4d859ed7 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1205,7 +1205,7 @@ static __poll_t dn_poll(struct file *file, struct socket *sock, poll_table *wai struct dn_scp *scp = DN_SK(sk); __poll_t mask = datagram_poll(file, sock, wait); - if (!skb_queue_empty(&scp->other_receive_queue)) + if (!skb_queue_empty_lockless(&scp->other_receive_queue)) mask |= EPOLLRDBAND; return mask; diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 73002022c9d820df95b9df1841ce3724c4d41070..716d265ba8ca95e88afeb3788b316a25fe331c38 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -46,7 +46,7 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index) dst->index = index; INIT_LIST_HEAD(&dst->list); - list_add_tail(&dsa_tree_list, &dst->list); + list_add_tail(&dst->list, &dsa_tree_list); kref_init(&dst->refcount); diff --git a/net/dsa/master.c b/net/dsa/master.c index a8e52c9967f4c1a9c24a5c91f143e09b6136b569..3255dfc97f865b1c2e4634d9f4a48925b7a1804a 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c @@ -310,8 +310,6 @@ static void dsa_master_reset_mtu(struct net_device *dev) rtnl_unlock(); } -static struct lock_class_key dsa_master_addr_list_lock_key; - int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) { int ret; @@ -325,9 +323,6 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) wmb(); dev->dsa_ptr = cpu_dp; - lockdep_set_class(&dev->addr_list_lock, - &dsa_master_addr_list_lock_key); - ret = dsa_master_ethtool_setup(dev); if (ret) return ret; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 75d58229a4bd356a18375a4e0c9e22e9e9a64082..028e65f4b5bafc93af03820055dab72fef4f708f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1341,15 +1341,6 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) return ret; } -static struct lock_class_key dsa_slave_netdev_xmit_lock_key; -static void dsa_slave_set_lockdep_class_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, - &dsa_slave_netdev_xmit_lock_key); -} - int dsa_slave_suspend(struct net_device *slave_dev) { struct dsa_port *dp = dsa_slave_to_port(slave_dev); @@ -1433,9 +1424,6 @@ int dsa_slave_create(struct dsa_port *port) slave_dev->max_mtu = ETH_MAX_MTU; SET_NETDEV_DEVTYPE(slave_dev, &dsa_type); - netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one, - NULL); - SET_NETDEV_DEV(slave_dev, port->ds->dev); slave_dev->dev.of_node = port->dn; slave_dev->vlan_features = master->vlan_features; diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 3297e7fa99458b13c40609588f187d366cf37411..c0b107cdd7153f7fbafdc546fea3511740e6933b 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -58,13 +58,6 @@ static const struct header_ops lowpan_header_ops = { .create = lowpan_header_create, }; -static int lowpan_dev_init(struct net_device *ldev) -{ - netdev_lockdep_set_classes(ldev); - - return 0; -} - static int lowpan_open(struct net_device *dev) { if (!open_count) @@ -96,7 +89,6 @@ static int lowpan_get_iflink(const struct net_device *dev) } static const struct net_device_ops lowpan_netdev_ops = { - .ndo_init = lowpan_dev_init, .ndo_start_xmit = lowpan_xmit, .ndo_open = lowpan_open, .ndo_stop = lowpan_stop, diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 9a0fe0c2fa02c9707e6fc8c02529a48e84f7d680..4a8550c49202db13b17d5cf4ed1e44dd8852c212 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -73,7 +73,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len reuseport_has_conns(sk, true); sk->sk_state = TCP_ESTABLISHED; sk_set_txhash(sk); - inet->inet_id = jiffies; + inet->inet_id = prandom_u32(); sk_dst_set(sk, &rt->dst); err = 0; diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index dde77f72e03edc8423e98c6f8a4a349aa4e306ec..71c78d223dfd32b1b95ee9e9aeffdaa95fd1a8c6 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1148,7 +1148,7 @@ void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 new_metric) if (!(dev->flags & IFF_UP) || ifa->ifa_flags & (IFA_F_SECONDARY | IFA_F_NOPREFIXROUTE) || ipv4_is_zeronet(prefix) || - prefix == ifa->ifa_local || ifa->ifa_prefixlen == 32) + (prefix == ifa->ifa_local && ifa->ifa_prefixlen == 32)) return; /* add the new */ diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index a9183543ca305e1723317a3dfd34af29087b605a..eb30fc1770def741950215f59a4e3ab0f91c6293 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -906,7 +906,7 @@ static void inet_child_forget(struct sock *sk, struct request_sock *req, percpu_counter_inc(sk->sk_prot->orphan_count); if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(req)->tfo_listener) { - BUG_ON(tcp_sk(child)->fastopen_rsk != req); + BUG_ON(rcu_access_pointer(tcp_sk(child)->fastopen_rsk) != req); BUG_ON(sk != req->rsk_listener); /* Paranoid, to prevent race condition if @@ -915,7 +915,7 @@ static void inet_child_forget(struct sock *sk, struct request_sock *req, * Also to satisfy an assertion in * tcp_v4_destroy_sock(). */ - tcp_sk(child)->fastopen_rsk = NULL; + RCU_INIT_POINTER(tcp_sk(child)->fastopen_rsk, NULL); } inet_csk_destroy_sock(child); } @@ -934,7 +934,7 @@ struct sock *inet_csk_reqsk_queue_add(struct sock *sk, req->sk = child; req->dl_next = NULL; if (queue->rskq_accept_head == NULL) - queue->rskq_accept_head = req; + WRITE_ONCE(queue->rskq_accept_head, req); else queue->rskq_accept_tail->dl_next = req; queue->rskq_accept_tail = req; diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index bbb005eb5218c2765567b1d14ef564d2332479cc..7dc79b973e6edcc64e668e14c71c732ca1187e8f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -193,7 +193,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { struct inet_diag_meminfo minfo = { .idiag_rmem = sk_rmem_alloc_get(sk), - .idiag_wmem = sk->sk_wmem_queued, + .idiag_wmem = READ_ONCE(sk->sk_wmem_queued), .idiag_fmem = sk->sk_forward_alloc, .idiag_tmem = sk_wmem_alloc_get(sk), }; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 97824864e40d13bac71510920ae125c6a89fef1d..83fb00153018f16678e71695134f7ae4d30ee0a3 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -240,7 +240,7 @@ static inline int compute_score(struct sock *sk, struct net *net, return -1; score = sk->sk_family == PF_INET ? 2 : 1; - if (sk->sk_incoming_cpu == raw_smp_processor_id()) + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) score++; } return score; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 52690bb3e40f9f52d533e531838e34fdebdcf3cf..10636fb6093e3cba09cfe6835077edb664e7244d 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -509,9 +509,9 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev) key = &tun_info->key; if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT)) goto err_free_skb; - md = ip_tunnel_info_opts(tun_info); - if (!md) + if (tun_info->options_len < sizeof(*md)) goto err_free_skb; + md = ip_tunnel_info_opts(tun_info); /* ERSPAN has fixed 8 byte GRE header */ version = md->version; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 28fca408812c5576fc4ea957c1c4dec97ec8faf3..3d8baaaf7086dba0c8fde178891734b2da7d7ec7 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -645,11 +645,12 @@ void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter) EXPORT_SYMBOL(ip_fraglist_prepare); void ip_frag_init(struct sk_buff *skb, unsigned int hlen, - unsigned int ll_rs, unsigned int mtu, + unsigned int ll_rs, unsigned int mtu, bool DF, struct ip_frag_state *state) { struct iphdr *iph = ip_hdr(skb); + state->DF = DF; state->hlen = hlen; state->ll_rs = ll_rs; state->mtu = mtu; @@ -668,9 +669,6 @@ static void ip_frag_ipcb(struct sk_buff *from, struct sk_buff *to, /* Copy the flags to each fragment. */ IPCB(to)->flags = IPCB(from)->flags; - if (IPCB(from)->flags & IPSKB_FRAG_PMTU) - state->iph->frag_off |= htons(IP_DF); - /* ANK: dirty, but effective trick. Upgrade options only if * the segment to be fragmented was THE FIRST (otherwise, * options are already fixed) and make it ONCE @@ -738,6 +736,8 @@ struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state) */ iph = ip_hdr(skb2); iph->frag_off = htons((state->offset >> 3)); + if (state->DF) + iph->frag_off |= htons(IP_DF); /* * Added AC : If we are fragmenting a fragment that's not the @@ -771,6 +771,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, struct rtable *rt = skb_rtable(skb); unsigned int mtu, hlen, ll_rs; struct ip_fraglist_iter iter; + ktime_t tstamp = skb->tstamp; struct ip_frag_state state; int err = 0; @@ -846,6 +847,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ip_fraglist_prepare(skb, &iter); } + skb->tstamp = tstamp; err = output(net, sk, skb); if (!err) @@ -881,7 +883,8 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, * Fragment the datagram. */ - ip_frag_init(skb, hlen, ll_rs, mtu, &state); + ip_frag_init(skb, hlen, ll_rs, mtu, IPCB(skb)->flags & IPSKB_FRAG_PMTU, + &state); /* * Keep copying data until we run out. @@ -900,6 +903,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, /* * Put this fragment into the sending queue. */ + skb2->tstamp = tstamp; err = output(net, sk, skb2); if (err) goto fail; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 14654876127e4f166d14b19975d707eae8637279..621f83434b2494784ec2b92824a2743be8817e21 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1482,7 +1482,7 @@ static bool rt_cache_route(struct fib_nh_common *nhc, struct rtable *rt) prev = cmpxchg(p, orig, rt); if (prev == orig) { if (orig) { - dst_dev_put(&orig->dst); + rt_add_uncached_list(orig); dst_release(&orig->dst); } } else { @@ -2470,14 +2470,17 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4, int orig_oif = fl4->flowi4_oif; unsigned int flags = 0; struct rtable *rth; - int err = -ENETUNREACH; + int err; if (fl4->saddr) { - rth = ERR_PTR(-EINVAL); if (ipv4_is_multicast(fl4->saddr) || ipv4_is_lbcast(fl4->saddr) || - ipv4_is_zeronet(fl4->saddr)) + ipv4_is_zeronet(fl4->saddr)) { + rth = ERR_PTR(-EINVAL); goto out; + } + + rth = ERR_PTR(-ENETUNREACH); /* I removed check for oif == dev_out->oif here. It was wrong for two reasons: diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f98a1882e537dca0102e829cb349be50302d83ab..d8876f0e9672718b4e02bc7aaaac30ecfd4903cb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -326,7 +326,7 @@ void tcp_enter_memory_pressure(struct sock *sk) { unsigned long val; - if (tcp_memory_pressure) + if (READ_ONCE(tcp_memory_pressure)) return; val = jiffies; @@ -341,7 +341,7 @@ void tcp_leave_memory_pressure(struct sock *sk) { unsigned long val; - if (!tcp_memory_pressure) + if (!READ_ONCE(tcp_memory_pressure)) return; val = xchg(&tcp_memory_pressure, 0); if (val) @@ -450,8 +450,8 @@ void tcp_init_sock(struct sock *sk) icsk->icsk_sync_mss = tcp_sync_mss; - sk->sk_sndbuf = sock_net(sk)->ipv4.sysctl_tcp_wmem[1]; - sk->sk_rcvbuf = sock_net(sk)->ipv4.sysctl_tcp_rmem[1]; + WRITE_ONCE(sk->sk_sndbuf, sock_net(sk)->ipv4.sysctl_tcp_wmem[1]); + WRITE_ONCE(sk->sk_rcvbuf, sock_net(sk)->ipv4.sysctl_tcp_rmem[1]); sk_sockets_allocated_inc(sk); sk->sk_route_forced_caps = NETIF_F_GSO; @@ -477,7 +477,7 @@ static void tcp_tx_timestamp(struct sock *sk, u16 tsflags) static inline bool tcp_stream_is_readable(const struct tcp_sock *tp, int target, struct sock *sk) { - return (tp->rcv_nxt - tp->copied_seq >= target) || + return (READ_ONCE(tp->rcv_nxt) - READ_ONCE(tp->copied_seq) >= target) || (sk->sk_prot->stream_memory_read ? sk->sk_prot->stream_memory_read(sk) : false); } @@ -543,10 +543,10 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait) /* Connected or passive Fast Open socket? */ if (state != TCP_SYN_SENT && - (state != TCP_SYN_RECV || tp->fastopen_rsk)) { + (state != TCP_SYN_RECV || rcu_access_pointer(tp->fastopen_rsk))) { int target = sock_rcvlowat(sk, 0, INT_MAX); - if (tp->urg_seq == tp->copied_seq && + if (READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq) && !sock_flag(sk, SOCK_URGINLINE) && tp->urg_data) target++; @@ -584,7 +584,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait) } /* This barrier is coupled with smp_wmb() in tcp_reset() */ smp_rmb(); - if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) + if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) mask |= EPOLLERR; return mask; @@ -607,7 +607,8 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) unlock_sock_fast(sk, slow); break; case SIOCATMARK: - answ = tp->urg_data && tp->urg_seq == tp->copied_seq; + answ = tp->urg_data && + READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq); break; case SIOCOUTQ: if (sk->sk_state == TCP_LISTEN) @@ -616,7 +617,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) answ = 0; else - answ = tp->write_seq - tp->snd_una; + answ = READ_ONCE(tp->write_seq) - tp->snd_una; break; case SIOCOUTQNSD: if (sk->sk_state == TCP_LISTEN) @@ -625,7 +626,8 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) answ = 0; else - answ = tp->write_seq - tp->snd_nxt; + answ = READ_ONCE(tp->write_seq) - + READ_ONCE(tp->snd_nxt); break; default: return -ENOIOCTLCMD; @@ -657,7 +659,7 @@ static void skb_entail(struct sock *sk, struct sk_buff *skb) tcb->sacked = 0; __skb_header_release(skb); tcp_add_write_queue_tail(sk, skb); - sk->sk_wmem_queued += skb->truesize; + sk_wmem_queued_add(sk, skb->truesize); sk_mem_charge(sk, skb->truesize); if (tp->nonagle & TCP_NAGLE_PUSH) tp->nonagle &= ~TCP_NAGLE_PUSH; @@ -1032,10 +1034,10 @@ ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, skb->len += copy; skb->data_len += copy; skb->truesize += copy; - sk->sk_wmem_queued += copy; + sk_wmem_queued_add(sk, copy); sk_mem_charge(sk, copy); skb->ip_summed = CHECKSUM_PARTIAL; - tp->write_seq += copy; + WRITE_ONCE(tp->write_seq, tp->write_seq + copy); TCP_SKB_CB(skb)->end_seq += copy; tcp_skb_pcount_set(skb, 0); @@ -1362,7 +1364,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) if (!copied) TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH; - tp->write_seq += copy; + WRITE_ONCE(tp->write_seq, tp->write_seq + copy); TCP_SKB_CB(skb)->end_seq += copy; tcp_skb_pcount_set(skb, 0); @@ -1668,9 +1670,9 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, sk_eat_skb(sk, skb); if (!desc->count) break; - tp->copied_seq = seq; + WRITE_ONCE(tp->copied_seq, seq); } - tp->copied_seq = seq; + WRITE_ONCE(tp->copied_seq, seq); tcp_rcv_space_adjust(sk); @@ -1699,7 +1701,7 @@ int tcp_set_rcvlowat(struct sock *sk, int val) else cap = sock_net(sk)->ipv4.sysctl_tcp_rmem[2] >> 1; val = min(val, cap); - sk->sk_rcvlowat = val ? : 1; + WRITE_ONCE(sk->sk_rcvlowat, val ? : 1); /* Check if we need to signal EPOLLIN right now */ tcp_data_ready(sk); @@ -1709,7 +1711,7 @@ int tcp_set_rcvlowat(struct sock *sk, int val) val <<= 1; if (val > sk->sk_rcvbuf) { - sk->sk_rcvbuf = val; + WRITE_ONCE(sk->sk_rcvbuf, val); tcp_sk(sk)->window_clamp = tcp_win_from_space(sk, val); } return 0; @@ -1819,7 +1821,7 @@ static int tcp_zerocopy_receive(struct sock *sk, out: up_read(¤t->mm->mmap_sem); if (length) { - tp->copied_seq = seq; + WRITE_ONCE(tp->copied_seq, seq); tcp_rcv_space_adjust(sk); /* Clean up data we have read: This will do ACK frames. */ @@ -1962,7 +1964,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, if (unlikely(flags & MSG_ERRQUEUE)) return inet_recv_error(sk, msg, len, addr_len); - if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) && + if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue) && (sk->sk_state == TCP_ESTABLISHED)) sk_busy_loop(sk, nonblock); @@ -2117,7 +2119,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, if (urg_offset < used) { if (!urg_offset) { if (!sock_flag(sk, SOCK_URGINLINE)) { - ++*seq; + WRITE_ONCE(*seq, *seq + 1); urg_hole++; offset++; used--; @@ -2139,7 +2141,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, } } - *seq += used; + WRITE_ONCE(*seq, *seq + used); copied += used; len -= used; @@ -2166,7 +2168,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, found_fin_ok: /* Process the FIN. */ - ++*seq; + WRITE_ONCE(*seq, *seq + 1); if (!(flags & MSG_PEEK)) sk_eat_skb(sk, skb); break; @@ -2487,7 +2489,10 @@ void tcp_close(struct sock *sk, long timeout) } if (sk->sk_state == TCP_CLOSE) { - struct request_sock *req = tcp_sk(sk)->fastopen_rsk; + struct request_sock *req; + + req = rcu_dereference_protected(tcp_sk(sk)->fastopen_rsk, + lockdep_sock_is_held(sk)); /* We could get here with a non-NULL req if the socket is * aborted (e.g., closed with unread data) before 3WHS * finishes. @@ -2559,6 +2564,7 @@ int tcp_disconnect(struct sock *sk, int flags) struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); int old_state = sk->sk_state; + u32 seq; if (old_state != TCP_CLOSE) tcp_set_state(sk, TCP_CLOSE); @@ -2585,7 +2591,7 @@ int tcp_disconnect(struct sock *sk, int flags) __kfree_skb(sk->sk_rx_skb_cache); sk->sk_rx_skb_cache = NULL; } - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); tp->urg_data = 0; tcp_write_queue_purge(sk); tcp_fastopen_active_disable_ofo_check(sk); @@ -2601,9 +2607,12 @@ int tcp_disconnect(struct sock *sk, int flags) tp->srtt_us = 0; tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); tp->rcv_rtt_last_tsecr = 0; - tp->write_seq += tp->max_window + 2; - if (tp->write_seq == 0) - tp->write_seq = 1; + + seq = tp->write_seq + tp->max_window + 2; + if (!seq) + seq = 1; + WRITE_ONCE(tp->write_seq, seq); + icsk->icsk_backoff = 0; tp->snd_cwnd = 2; icsk->icsk_probes_out = 0; @@ -2930,9 +2939,9 @@ static int do_tcp_setsockopt(struct sock *sk, int level, if (sk->sk_state != TCP_CLOSE) err = -EPERM; else if (tp->repair_queue == TCP_SEND_QUEUE) - tp->write_seq = val; + WRITE_ONCE(tp->write_seq, val); else if (tp->repair_queue == TCP_RECV_QUEUE) - tp->rcv_nxt = val; + WRITE_ONCE(tp->rcv_nxt, val); else err = -EINVAL; break; @@ -3831,7 +3840,13 @@ EXPORT_SYMBOL(tcp_md5_hash_key); void tcp_done(struct sock *sk) { - struct request_sock *req = tcp_sk(sk)->fastopen_rsk; + struct request_sock *req; + + /* We might be called with a new socket, after + * inet_csk_prepare_forced_close() has been called + * so we can not use lockdep_sock_is_held(sk) + */ + req = rcu_dereference_protected(tcp_sk(sk)->fastopen_rsk, 1); if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS); diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index 81a8221d650a94be53d17354c60ddd0c655eaccf..549506162ddeca22f6dd87dfe1c5c13cea6e2b69 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c @@ -26,8 +26,9 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, } else if (sk->sk_type == SOCK_STREAM) { const struct tcp_sock *tp = tcp_sk(sk); - r->idiag_rqueue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0); - r->idiag_wqueue = tp->write_seq - tp->snd_una; + r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) - + READ_ONCE(tp->copied_seq), 0); + r->idiag_wqueue = READ_ONCE(tp->write_seq) - tp->snd_una; } if (info) tcp_get_info(sk, info); diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 3fd451271a7034aab65f02f2bc331254b49f2153..a915ade0c81803a3b190e8c0513220b4e67c35e4 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -253,7 +253,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk, */ tp = tcp_sk(child); - tp->fastopen_rsk = req; + rcu_assign_pointer(tp->fastopen_rsk, req); tcp_rsk(req)->tfo_listener = true; /* RFC1323: The window in SYN & SYN/ACK segments is never diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3578357abe30e92f818e5b9acf3317be1d997af5..a2e52ad7cdab3e66a469a8ca850848988b3888d7 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -359,7 +359,8 @@ static void tcp_sndbuf_expand(struct sock *sk) sndmem *= nr_segs * per_mss; if (sk->sk_sndbuf < sndmem) - sk->sk_sndbuf = min(sndmem, sock_net(sk)->ipv4.sysctl_tcp_wmem[2]); + WRITE_ONCE(sk->sk_sndbuf, + min(sndmem, sock_net(sk)->ipv4.sysctl_tcp_wmem[2])); } /* 2. Tuning advertised window (window_clamp, rcv_ssthresh) @@ -483,8 +484,9 @@ static void tcp_clamp_window(struct sock *sk) !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) && !tcp_under_memory_pressure(sk) && sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)) { - sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc), - net->ipv4.sysctl_tcp_rmem[2]); + WRITE_ONCE(sk->sk_rcvbuf, + min(atomic_read(&sk->sk_rmem_alloc), + net->ipv4.sysctl_tcp_rmem[2])); } if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) tp->rcv_ssthresh = min(tp->window_clamp, 2U * tp->advmss); @@ -648,7 +650,7 @@ void tcp_rcv_space_adjust(struct sock *sk) rcvbuf = min_t(u64, rcvwin * rcvmem, sock_net(sk)->ipv4.sysctl_tcp_rmem[2]); if (rcvbuf > sk->sk_rcvbuf) { - sk->sk_rcvbuf = rcvbuf; + WRITE_ONCE(sk->sk_rcvbuf, rcvbuf); /* Make the window clamp follow along. */ tp->window_clamp = tcp_win_from_space(sk, rcvbuf); @@ -2666,7 +2668,7 @@ static void tcp_process_loss(struct sock *sk, int flag, int num_dupack, struct tcp_sock *tp = tcp_sk(sk); bool recovered = !before(tp->snd_una, tp->high_seq); - if ((flag & FLAG_SND_UNA_ADVANCED || tp->fastopen_rsk) && + if ((flag & FLAG_SND_UNA_ADVANCED || rcu_access_pointer(tp->fastopen_rsk)) && tcp_try_undo_loss(sk, false)) return; @@ -2990,7 +2992,7 @@ void tcp_rearm_rto(struct sock *sk) /* If the retrans timer is currently being used by Fast Open * for SYN-ACK retrans purpose, stay put. */ - if (tp->fastopen_rsk) + if (rcu_access_pointer(tp->fastopen_rsk)) return; if (!tp->packets_out) { @@ -3362,7 +3364,7 @@ static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq) sock_owned_by_me((struct sock *)tp); tp->bytes_received += delta; - tp->rcv_nxt = seq; + WRITE_ONCE(tp->rcv_nxt, seq); } /* Update our send window. @@ -5356,7 +5358,7 @@ static void tcp_check_urg(struct sock *sk, const struct tcphdr *th) } tp->urg_data = TCP_URG_NOTYET; - tp->urg_seq = ptr; + WRITE_ONCE(tp->urg_seq, ptr); /* Disable header prediction. */ tp->pred_flags = 0; @@ -5932,7 +5934,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, /* Ok.. it's good. Set up sequence numbers and * move to established. */ - tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; + WRITE_ONCE(tp->rcv_nxt, TCP_SKB_CB(skb)->seq + 1); tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; /* RFC1323: The window in SYN & SYN/ACK segments is @@ -5961,7 +5963,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, /* Remember, tcp_poll() does not lock socket! * Change state from SYN-SENT only after copied_seq * is initialized. */ - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); smc_check_reset_syn(tp); @@ -6035,8 +6037,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tp->tcp_header_len = sizeof(struct tcphdr); } - tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->rcv_nxt, TCP_SKB_CB(skb)->seq + 1); + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; /* RFC1323: The window in SYN & SYN/ACK segments is @@ -6087,6 +6089,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, static void tcp_rcv_synrecv_state_fastopen(struct sock *sk) { + struct request_sock *req; + tcp_try_undo_loss(sk, false); /* Reset rtx states to prevent spurious retransmits_timed_out() */ @@ -6096,7 +6100,9 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk) /* Once we leave TCP_SYN_RECV or TCP_FIN_WAIT_1, * we no longer need req so release it. */ - reqsk_fastopen_remove(sk, tcp_sk(sk)->fastopen_rsk, false); + req = rcu_dereference_protected(tcp_sk(sk)->fastopen_rsk, + lockdep_sock_is_held(sk)); + reqsk_fastopen_remove(sk, req, false); /* Re-arm the timer because data may have been sent out. * This is similar to the regular data transmission case @@ -6171,7 +6177,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) tcp_mstamp_refresh(tp); tp->rx_opt.saw_tstamp = 0; - req = tp->fastopen_rsk; + req = rcu_dereference_protected(tp->fastopen_rsk, + lockdep_sock_is_held(sk)); if (req) { bool req_stolen; @@ -6211,7 +6218,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) tcp_try_undo_spurious_syn(sk); tp->retrans_stamp = 0; tcp_init_transfer(sk, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB); - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); } smp_mb(); tcp_set_state(sk, TCP_ESTABLISHED); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index bf124b1742df864a3007d137ff31c8bfb2bee12a..67b2dc7a17274bd4cdadd01c45a9afdc66dc01d3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -164,9 +164,11 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) * without appearing to create any others. */ if (likely(!tp->repair)) { - tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2; - if (tp->write_seq == 0) - tp->write_seq = 1; + u32 seq = tcptw->tw_snd_nxt + 65535 + 2; + + if (!seq) + seq = 1; + WRITE_ONCE(tp->write_seq, seq); tp->rx_opt.ts_recent = tcptw->tw_ts_recent; tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; } @@ -253,7 +255,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) tp->rx_opt.ts_recent = 0; tp->rx_opt.ts_recent_stamp = 0; if (likely(!tp->repair)) - tp->write_seq = 0; + WRITE_ONCE(tp->write_seq, 0); } inet->inet_dport = usin->sin_port; @@ -291,16 +293,17 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (likely(!tp->repair)) { if (!tp->write_seq) - tp->write_seq = secure_tcp_seq(inet->inet_saddr, - inet->inet_daddr, - inet->inet_sport, - usin->sin_port); + WRITE_ONCE(tp->write_seq, + secure_tcp_seq(inet->inet_saddr, + inet->inet_daddr, + inet->inet_sport, + usin->sin_port)); tp->tsoffset = secure_tcp_ts_off(sock_net(sk), inet->inet_saddr, inet->inet_daddr); } - inet->inet_id = tp->write_seq ^ jiffies; + inet->inet_id = prandom_u32(); if (tcp_fastopen_defer_connect(sk, &err)) return err; @@ -478,7 +481,7 @@ int tcp_v4_err(struct sk_buff *icmp_skb, u32 info) icsk = inet_csk(sk); tp = tcp_sk(sk); /* XXX (TFO) - tp->snd_una should be ISN (tcp_create_openreq_child() */ - fastopen = tp->fastopen_rsk; + fastopen = rcu_dereference(tp->fastopen_rsk); snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una; if (sk->sk_state != TCP_LISTEN && !between(seq, snd_una, tp->snd_nxt)) { @@ -1447,7 +1450,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, inet_csk(newsk)->icsk_ext_hdr_len = 0; if (inet_opt) inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; - newinet->inet_id = newtp->write_seq ^ jiffies; + newinet->inet_id = prandom_u32(); if (!dst) { dst = inet_csk_route_child_sock(sk, newsk, req); @@ -1644,7 +1647,7 @@ int tcp_v4_early_demux(struct sk_buff *skb) bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb) { - u32 limit = sk->sk_rcvbuf + sk->sk_sndbuf; + u32 limit = READ_ONCE(sk->sk_rcvbuf) + READ_ONCE(sk->sk_sndbuf); struct skb_shared_info *shinfo; const struct tcphdr *th; struct tcphdr *thtail; @@ -2121,7 +2124,7 @@ void tcp_v4_destroy_sock(struct sock *sk) if (inet_csk(sk)->icsk_bind_hash) inet_put_port(sk); - BUG_ON(tp->fastopen_rsk); + BUG_ON(rcu_access_pointer(tp->fastopen_rsk)); /* If socket is aborted during connect operation */ tcp_free_fastopen_req(tp); @@ -2455,12 +2458,13 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i) /* Because we don't lock the socket, * we might find a transient negative value. */ - rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0); + rx_queue = max_t(int, READ_ONCE(tp->rcv_nxt) - + READ_ONCE(tp->copied_seq), 0); seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d", i, src, srcp, dest, destp, state, - tp->write_seq - tp->snd_una, + READ_ONCE(tp->write_seq) - tp->snd_una, rx_queue, timer_active, jiffies_delta_to_clock_t(timer_expires - jiffies), @@ -2677,7 +2681,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.tcp_death_row.sysctl_max_tw_buckets = cnt / 2; net->ipv4.tcp_death_row.hashinfo = &tcp_hashinfo; - net->ipv4.sysctl_max_syn_backlog = max(128, cnt / 256); + net->ipv4.sysctl_max_syn_backlog = max(128, cnt / 128); net->ipv4.sysctl_tcp_sack = 1; net->ipv4.sysctl_tcp_window_scaling = 1; net->ipv4.sysctl_tcp_timestamps = 1; diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index bb140a5db8c066e57f1018fd47bccd4628def642..c802bc80c4006f82c2e9189ef1fc11b8f321e70d 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -462,6 +462,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, struct tcp_request_sock *treq = tcp_rsk(req); struct inet_connection_sock *newicsk; struct tcp_sock *oldtp, *newtp; + u32 seq; if (!newsk) return NULL; @@ -475,12 +476,16 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, /* Now setup tcp_sock */ newtp->pred_flags = 0; - newtp->rcv_wup = newtp->copied_seq = - newtp->rcv_nxt = treq->rcv_isn + 1; + seq = treq->rcv_isn + 1; + newtp->rcv_wup = seq; + WRITE_ONCE(newtp->copied_seq, seq); + WRITE_ONCE(newtp->rcv_nxt, seq); newtp->segs_in = 1; - newtp->snd_sml = newtp->snd_una = - newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1; + seq = treq->snt_isn + 1; + newtp->snd_sml = newtp->snd_una = seq; + WRITE_ONCE(newtp->snd_nxt, seq); + newtp->snd_up = seq; INIT_LIST_HEAD(&newtp->tsq_node); INIT_LIST_HEAD(&newtp->tsorted_sent_queue); @@ -495,7 +500,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, newtp->total_retrans = req->num_retrans; tcp_init_xmit_timers(newsk); - newtp->write_seq = newtp->pushed_seq = treq->snt_isn + 1; + WRITE_ONCE(newtp->write_seq, newtp->pushed_seq = treq->snt_isn + 1); if (sock_flag(newsk, SOCK_KEEPOPEN)) inet_csk_reset_keepalive_timer(newsk, @@ -541,7 +546,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, newtp->rx_opt.mss_clamp = req->mss; tcp_ecn_openreq_child(newtp, req); newtp->fastopen_req = NULL; - newtp->fastopen_rsk = NULL; + RCU_INIT_POINTER(newtp->fastopen_rsk, NULL); __TCP_INC_STATS(sock_net(sk), TCP_MIB_PASSIVEOPENS); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index fec6d67bfd146dc78f0f25173fd71b8b8cc752fe..0488607c5cd3615633af207f0bb41bea0c0176ce 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -67,7 +67,7 @@ static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); unsigned int prior_packets = tp->packets_out; - tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; + WRITE_ONCE(tp->snd_nxt, TCP_SKB_CB(skb)->end_seq); __skb_unlink(skb, &sk->sk_write_queue); tcp_rbtree_insert(&sk->tcp_rtx_queue, skb); @@ -1196,10 +1196,10 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) struct tcp_sock *tp = tcp_sk(sk); /* Advance write_seq and place onto the write_queue. */ - tp->write_seq = TCP_SKB_CB(skb)->end_seq; + WRITE_ONCE(tp->write_seq, TCP_SKB_CB(skb)->end_seq); __skb_header_release(skb); tcp_add_write_queue_tail(sk, skb); - sk->sk_wmem_queued += skb->truesize; + sk_wmem_queued_add(sk, skb->truesize); sk_mem_charge(sk, skb->truesize); } @@ -1333,7 +1333,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue, return -ENOMEM; /* We'll just try again later. */ skb_copy_decrypted(buff, skb); - sk->sk_wmem_queued += buff->truesize; + sk_wmem_queued_add(sk, buff->truesize); sk_mem_charge(sk, buff->truesize); nlen = skb->len - len - nsize; buff->truesize += nlen; @@ -1443,7 +1443,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) if (delta_truesize) { skb->truesize -= delta_truesize; - sk->sk_wmem_queued -= delta_truesize; + sk_wmem_queued_add(sk, -delta_truesize); sk_mem_uncharge(sk, delta_truesize); sock_set_flag(sk, SOCK_QUEUE_SHRUNK); } @@ -1888,7 +1888,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, return -ENOMEM; skb_copy_decrypted(buff, skb); - sk->sk_wmem_queued += buff->truesize; + sk_wmem_queued_add(sk, buff->truesize); sk_mem_charge(sk, buff->truesize); buff->truesize += nlen; skb->truesize -= nlen; @@ -2152,7 +2152,7 @@ static int tcp_mtu_probe(struct sock *sk) nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false); if (!nskb) return -1; - sk->sk_wmem_queued += nskb->truesize; + sk_wmem_queued_add(sk, nskb->truesize); sk_mem_charge(sk, nskb->truesize); skb = tcp_send_head(sk); @@ -2482,7 +2482,7 @@ bool tcp_schedule_loss_probe(struct sock *sk, bool advancing_rto) /* Don't do any loss probe on a Fast Open connection before 3WHS * finishes. */ - if (tp->fastopen_rsk) + if (rcu_access_pointer(tp->fastopen_rsk)) return false; early_retrans = sock_net(sk)->ipv4.sysctl_tcp_early_retrans; @@ -3142,7 +3142,7 @@ void tcp_send_fin(struct sock *sk) * if FIN had been sent. This is because retransmit path * does not change tp->snd_nxt. */ - tp->snd_nxt++; + WRITE_ONCE(tp->snd_nxt, tp->snd_nxt + 1); return; } } else { @@ -3222,7 +3222,7 @@ int tcp_send_synack(struct sock *sk) tcp_rtx_queue_unlink_and_free(skb, sk); __skb_header_release(nskb); tcp_rbtree_insert(&sk->tcp_rtx_queue, nskb); - sk->sk_wmem_queued += nskb->truesize; + sk_wmem_queued_add(sk, nskb->truesize); sk_mem_charge(sk, nskb->truesize); skb = nskb; } @@ -3426,14 +3426,14 @@ static void tcp_connect_init(struct sock *sk) tp->snd_una = tp->write_seq; tp->snd_sml = tp->write_seq; tp->snd_up = tp->write_seq; - tp->snd_nxt = tp->write_seq; + WRITE_ONCE(tp->snd_nxt, tp->write_seq); if (likely(!tp->repair)) tp->rcv_nxt = 0; else tp->rcv_tstamp = tcp_jiffies32; tp->rcv_wup = tp->rcv_nxt; - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); inet_csk(sk)->icsk_rto = tcp_timeout_init(sk); inet_csk(sk)->icsk_retransmits = 0; @@ -3447,9 +3447,9 @@ static void tcp_connect_queue_skb(struct sock *sk, struct sk_buff *skb) tcb->end_seq += skb->len; __skb_header_release(skb); - sk->sk_wmem_queued += skb->truesize; + sk_wmem_queued_add(sk, skb->truesize); sk_mem_charge(sk, skb->truesize); - tp->write_seq = tcb->end_seq; + WRITE_ONCE(tp->write_seq, tcb->end_seq); tp->packets_out += tcp_skb_pcount(skb); } @@ -3586,11 +3586,11 @@ int tcp_connect(struct sock *sk) /* We change tp->snd_nxt after the tcp_transmit_skb() call * in order to make this packet get counted in tcpOutSegs. */ - tp->snd_nxt = tp->write_seq; + WRITE_ONCE(tp->snd_nxt, tp->write_seq); tp->pushed_seq = tp->write_seq; buff = tcp_send_head(sk); if (unlikely(buff)) { - tp->snd_nxt = TCP_SKB_CB(buff)->seq; + WRITE_ONCE(tp->snd_nxt, TCP_SKB_CB(buff)->seq); tp->pushed_seq = TCP_SKB_CB(buff)->seq; } TCP_INC_STATS(sock_net(sk), TCP_MIB_ACTIVEOPENS); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 05be564414e9b4aad64321e381fc0afa10980190..dd5a6317a8018a45ad609f832ced6df2937ad453 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -386,15 +386,13 @@ abort: tcp_write_err(sk); * Timer for Fast Open socket to retransmit SYNACK. Note that the * sk here is the child socket, not the parent (listener) socket. */ -static void tcp_fastopen_synack_timer(struct sock *sk) +static void tcp_fastopen_synack_timer(struct sock *sk, struct request_sock *req) { struct inet_connection_sock *icsk = inet_csk(sk); int max_retries = icsk->icsk_syn_retries ? : sock_net(sk)->ipv4.sysctl_tcp_synack_retries + 1; /* add one more retry for fastopen */ struct tcp_sock *tp = tcp_sk(sk); - struct request_sock *req; - req = tcp_sk(sk)->fastopen_rsk; req->rsk_ops->syn_ack_timeout(req); if (req->num_timeout >= max_retries) { @@ -435,11 +433,14 @@ void tcp_retransmit_timer(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); struct net *net = sock_net(sk); struct inet_connection_sock *icsk = inet_csk(sk); + struct request_sock *req; - if (tp->fastopen_rsk) { + req = rcu_dereference_protected(tp->fastopen_rsk, + lockdep_sock_is_held(sk)); + if (req) { WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && sk->sk_state != TCP_FIN_WAIT1); - tcp_fastopen_synack_timer(sk); + tcp_fastopen_synack_timer(sk, req); /* Before we receive ACK to our SYN-ACK don't retransmit * anything else (e.g., data or FIN segments). */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 14bc654b6842003b325efe268041749c6770947f..1d58ce829dcae476a7a32a6ab5fa8bb91ec8ae67 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -388,7 +388,7 @@ static int compute_score(struct sock *sk, struct net *net, return -1; score += 4; - if (sk->sk_incoming_cpu == raw_smp_processor_id()) + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) score++; return score; } @@ -1316,6 +1316,20 @@ static void udp_set_dev_scratch(struct sk_buff *skb) scratch->_tsize_state |= UDP_SKB_IS_STATELESS; } +static void udp_skb_csum_unnecessary_set(struct sk_buff *skb) +{ + /* We come here after udp_lib_checksum_complete() returned 0. + * This means that __skb_checksum_complete() might have + * set skb->csum_valid to 1. + * On 64bit platforms, we can set csum_unnecessary + * to true, but only if the skb is not shared. + */ +#if BITS_PER_LONG == 64 + if (!skb_shared(skb)) + udp_skb_scratch(skb)->csum_unnecessary = true; +#endif +} + static int udp_skb_truesize(struct sk_buff *skb) { return udp_skb_scratch(skb)->_tsize_state & ~UDP_SKB_IS_STATELESS; @@ -1550,10 +1564,7 @@ static struct sk_buff *__first_packet_length(struct sock *sk, *total += skb->truesize; kfree_skb(skb); } else { - /* the csum related bits could be changed, refresh - * the scratch area - */ - udp_set_dev_scratch(skb); + udp_skb_csum_unnecessary_set(skb); break; } } @@ -1577,7 +1588,7 @@ static int first_packet_length(struct sock *sk) spin_lock_bh(&rcvq->lock); skb = __first_packet_length(sk, rcvq, &total); - if (!skb && !skb_queue_empty(sk_queue)) { + if (!skb && !skb_queue_empty_lockless(sk_queue)) { spin_lock(&sk_queue->lock); skb_queue_splice_tail_init(sk_queue, rcvq); spin_unlock(&sk_queue->lock); @@ -1650,7 +1661,7 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags, return skb; } - if (skb_queue_empty(sk_queue)) { + if (skb_queue_empty_lockless(sk_queue)) { spin_unlock_bh(&queue->lock); goto busy_check; } @@ -1676,7 +1687,7 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags, break; sk_busy_loop(sk, flags & MSG_DONTWAIT); - } while (!skb_queue_empty(sk_queue)); + } while (!skb_queue_empty_lockless(sk_queue)); /* sk_queue is empty, reader_queue may contain peeked packets */ } while (timeo && @@ -2712,7 +2723,7 @@ __poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait) __poll_t mask = datagram_poll(file, sock, wait); struct sock *sk = sock->sk; - if (!skb_queue_empty(&udp_sk(sk)->reader_queue)) + if (!skb_queue_empty_lockless(&udp_sk(sk)->reader_queue)) mask |= EPOLLIN | EPOLLRDNORM; /* Check for false positives due to checksum errors */ diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index 783f3c1466daca7ea3d348fa1cc766fcc9026d62..2fc079284ca43886652ce394d701b153d18cf32f 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c @@ -7,6 +7,7 @@ #include #include #include +#include #include /* if ipv6 module registers this function is used by xfrm to force all diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index cf60fae9533b230455d89007a9ac45af958f2efe..fbe9d4295eac38d247aca362d6006cdec2d7f7da 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -105,7 +105,7 @@ static inline int compute_score(struct sock *sk, struct net *net, return -1; score = 1; - if (sk->sk_incoming_cpu == raw_smp_processor_id()) + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) score++; } return score; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index d5779d6a60650ba9ce6a72d6246a829e2df733e0..923034c52ce40d85c91a54d1b107e2088d31bb85 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -980,9 +980,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, dsfield = key->tos; if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT)) goto tx_err; - md = ip_tunnel_info_opts(tun_info); - if (!md) + if (tun_info->options_len < sizeof(*md)) goto tx_err; + md = ip_tunnel_info_opts(tun_info); tun_id = tunnel_id_to_key32(key->tun_id); if (md->version == 1) { @@ -2192,6 +2192,7 @@ static void ip6erspan_tap_setup(struct net_device *dev) { ether_setup(dev); + dev->max_mtu = 0; dev->netdev_ops = &ip6erspan_netdev_ops; dev->needs_free_netdev = true; dev->priv_destructor = ip6gre_dev_free; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index edadee4a7e76105f737d705052db8f5bbc6c0152..71827b56c0063b56bcfbef4bd8910ddcec035824 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -768,6 +768,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, inet6_sk(skb->sk) : NULL; struct ip6_frag_state state; unsigned int mtu, hlen, nexthdr_offset; + ktime_t tstamp = skb->tstamp; int hroom, err = 0; __be32 frag_id; u8 *prevhdr, nexthdr = 0; @@ -855,6 +856,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, if (iter.frag) ip6_fraglist_prepare(skb, &iter); + skb->tstamp = tstamp; err = output(net, sk, skb); if (!err) IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), @@ -913,6 +915,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, /* * Put this fragment into the sending queue. */ + frag->tstamp = tstamp; err = output(net, sk, frag); if (err) goto fail; diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index a9bff556d3b2ddd5334d20a63210bad0dfa6cd2d..409e79b84a830dd22ffe7728f45d9dc65ec01df4 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -119,6 +119,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, struct sk_buff *)) { int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; + ktime_t tstamp = skb->tstamp; struct ip6_frag_state state; u8 *prevhdr, nexthdr = 0; unsigned int mtu, hlen; @@ -183,6 +184,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, if (iter.frag) ip6_fraglist_prepare(skb, &iter); + skb->tstamp = tstamp; err = output(net, sk, data, skb); if (err || !iter.frag) break; @@ -215,6 +217,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, goto blackhole; } + skb2->tstamp = tstamp; err = output(net, sk, data, skb2); if (err) goto blackhole; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e3d9f4559c99f252eba448845cce434bc53f3fd8..4804b6dc5e6519a457e631bc1438a14f85477567 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -215,7 +215,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, !ipv6_addr_equal(&sk->sk_v6_daddr, &usin->sin6_addr)) { tp->rx_opt.ts_recent = 0; tp->rx_opt.ts_recent_stamp = 0; - tp->write_seq = 0; + WRITE_ONCE(tp->write_seq, 0); } sk->sk_v6_daddr = usin->sin6_addr; @@ -311,10 +311,11 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, if (likely(!tp->repair)) { if (!tp->write_seq) - tp->write_seq = secure_tcpv6_seq(np->saddr.s6_addr32, - sk->sk_v6_daddr.s6_addr32, - inet->inet_sport, - inet->inet_dport); + WRITE_ONCE(tp->write_seq, + secure_tcpv6_seq(np->saddr.s6_addr32, + sk->sk_v6_daddr.s6_addr32, + inet->inet_sport, + inet->inet_dport)); tp->tsoffset = secure_tcpv6_ts_off(sock_net(sk), np->saddr.s6_addr32, sk->sk_v6_daddr.s6_addr32); @@ -406,7 +407,7 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, tp = tcp_sk(sk); /* XXX (TFO) - tp->snd_una should be ISN (tcp_create_openreq_child() */ - fastopen = tp->fastopen_rsk; + fastopen = rcu_dereference(tp->fastopen_rsk); snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una; if (sk->sk_state != TCP_LISTEN && !between(seq, snd_una, tp->snd_nxt)) { @@ -1895,7 +1896,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) /* Because we don't lock the socket, * we might find a transient negative value. */ - rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0); + rx_queue = max_t(int, READ_ONCE(tp->rcv_nxt) - + READ_ONCE(tp->copied_seq), 0); seq_printf(seq, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " @@ -1906,7 +1908,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) dest->s6_addr32[0], dest->s6_addr32[1], dest->s6_addr32[2], dest->s6_addr32[3], destp, state, - tp->write_seq - tp->snd_una, + READ_ONCE(tp->write_seq) - tp->snd_una, rx_queue, timer_active, jiffies_delta_to_clock_t(timer_expires - jiffies), diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 6324d3a8cb53dd76ea0deaf4358e33e529ce56ec..9fec580c968e0d331fcaf54289364526ebd902c2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -135,7 +135,7 @@ static int compute_score(struct sock *sk, struct net *net, return -1; score++; - if (sk->sk_incoming_cpu == raw_smp_processor_id()) + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) score++; return score; diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index fd5ac2788e45c5b8710aae54fd2df17cae325424..d3b520b9b2c9d226f90b579b7b40e8baf459f73a 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -56,7 +56,6 @@ static int l2tp_eth_dev_init(struct net_device *dev) { eth_hw_addr_random(dev); eth_broadcast_addr(dev->broadcast); - netdev_lockdep_set_classes(dev); return 0; } diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 2017b7d780f5af73c1ac7461113842776d1b00fc..c74f44dfaa22a5020880ea218c6607ace8fd5e22 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -113,22 +113,26 @@ static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr) * * Send data via reliable llc2 connection. * Returns 0 upon success, non-zero if action did not succeed. + * + * This function always consumes a reference to the skb. */ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) { struct llc_sock* llc = llc_sk(sk); - int rc = 0; if (unlikely(llc_data_accept_state(llc->state) || llc->remote_busy_flag || llc->p_flag)) { long timeout = sock_sndtimeo(sk, noblock); + int rc; rc = llc_ui_wait_for_busy_core(sk, timeout); + if (rc) { + kfree_skb(skb); + return rc; + } } - if (unlikely(!rc)) - rc = llc_build_and_send_pkt(sk, skb); - return rc; + return llc_build_and_send_pkt(sk, skb); } static void llc_ui_sk_init(struct socket *sock, struct sock *sk) @@ -899,7 +903,7 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name); int flags = msg->msg_flags; int noblock = flags & MSG_DONTWAIT; - struct sk_buff *skb; + struct sk_buff *skb = NULL; size_t size = 0; int rc = -EINVAL, copied = 0, hdrlen; @@ -908,10 +912,10 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) lock_sock(sk); if (addr) { if (msg->msg_namelen < sizeof(*addr)) - goto release; + goto out; } else { if (llc_ui_addr_null(&llc->addr)) - goto release; + goto out; addr = &llc->addr; } /* must bind connection to sap if user hasn't done it. */ @@ -919,7 +923,7 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) /* bind to sap with null dev, exclusive. */ rc = llc_ui_autobind(sock, addr); if (rc) - goto release; + goto out; } hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr); size = hdrlen + len; @@ -928,12 +932,12 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) copied = size - hdrlen; rc = -EINVAL; if (copied < 0) - goto release; + goto out; release_sock(sk); skb = sock_alloc_send_skb(sk, size, noblock, &rc); lock_sock(sk); if (!skb) - goto release; + goto out; skb->dev = llc->dev; skb->protocol = llc_proto_type(addr->sllc_arphrd); skb_reserve(skb, hdrlen); @@ -943,29 +947,31 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (sk->sk_type == SOCK_DGRAM || addr->sllc_ua) { llc_build_and_send_ui_pkt(llc->sap, skb, addr->sllc_mac, addr->sllc_sap); + skb = NULL; goto out; } if (addr->sllc_test) { llc_build_and_send_test_pkt(llc->sap, skb, addr->sllc_mac, addr->sllc_sap); + skb = NULL; goto out; } if (addr->sllc_xid) { llc_build_and_send_xid_pkt(llc->sap, skb, addr->sllc_mac, addr->sllc_sap); + skb = NULL; goto out; } rc = -ENOPROTOOPT; if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua)) goto out; rc = llc_ui_send_data(sk, skb, noblock); + skb = NULL; out: - if (rc) { - kfree_skb(skb); -release: + kfree_skb(skb); + if (rc) dprintk("%s: failed sending from %02X to %02X: %d\n", __func__, llc->laddr.lsap, llc->daddr.lsap, rc); - } release_sock(sk); return rc ? : copied; } diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 4d78375f9872d1a6962aa0e7cda7b913a6e0a7f3..647c0554d04cd89d19563f6ef5b609b9311fd911 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -372,6 +372,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) llc_pdu_init_as_i_cmd(skb, 1, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); if (likely(!rc)) { + skb_get(skb); llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } @@ -389,7 +390,8 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb) llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); if (likely(!rc)) { - rc = llc_conn_send_pdu(sk, skb); + skb_get(skb); + llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } return rc; @@ -406,6 +408,7 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); if (likely(!rc)) { + skb_get(skb); llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } @@ -916,7 +919,8 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk, llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); if (likely(!rc)) { - rc = llc_conn_send_pdu(sk, skb); + skb_get(skb); + llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } return rc; diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 4ff89cb7c86f785a175b048c0c7c6a82c2f8fe8c..7b620acaca9ec194e03b590c21fb004401dbc7ce 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -30,7 +30,7 @@ #endif static int llc_find_offset(int state, int ev_type); -static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *skb); +static void llc_conn_send_pdus(struct sock *sk); static int llc_conn_service(struct sock *sk, struct sk_buff *skb); static int llc_exec_conn_trans_actions(struct sock *sk, struct llc_conn_state_trans *trans, @@ -55,6 +55,8 @@ int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ; * (executing it's actions and changing state), upper layer will be * indicated or confirmed, if needed. Returns 0 for success, 1 for * failure. The socket lock has to be held before calling this function. + * + * This function always consumes a reference to the skb. */ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) { @@ -62,12 +64,6 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) struct llc_sock *llc = llc_sk(skb->sk); struct llc_conn_state_ev *ev = llc_conn_ev(skb); - /* - * We have to hold the skb, because llc_conn_service will kfree it in - * the sending path and we need to look at the skb->cb, where we encode - * llc_conn_state_ev. - */ - skb_get(skb); ev->ind_prim = ev->cfm_prim = 0; /* * Send event to state machine @@ -75,21 +71,12 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) rc = llc_conn_service(skb->sk, skb); if (unlikely(rc != 0)) { printk(KERN_ERR "%s: llc_conn_service failed\n", __func__); - goto out_kfree_skb; - } - - if (unlikely(!ev->ind_prim && !ev->cfm_prim)) { - /* indicate or confirm not required */ - if (!skb->next) - goto out_kfree_skb; goto out_skb_put; } - if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */ - skb_get(skb); - switch (ev->ind_prim) { case LLC_DATA_PRIM: + skb_get(skb); llc_save_primitive(sk, skb, LLC_DATA_PRIM); if (unlikely(sock_queue_rcv_skb(sk, skb))) { /* @@ -106,6 +93,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) * skb->sk pointing to the newly created struct sock in * llc_conn_handler. -acme */ + skb_get(skb); skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_state_change(sk); break; @@ -121,7 +109,6 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) sk->sk_state_change(sk); } } - kfree_skb(skb); sock_put(sk); break; case LLC_RESET_PRIM: @@ -130,14 +117,11 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) * RESET is not being notified to upper layers for now */ printk(KERN_INFO "%s: received a reset ind!\n", __func__); - kfree_skb(skb); break; default: - if (ev->ind_prim) { + if (ev->ind_prim) printk(KERN_INFO "%s: received unknown %d prim!\n", __func__, ev->ind_prim); - kfree_skb(skb); - } /* No indication */ break; } @@ -179,25 +163,22 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) printk(KERN_INFO "%s: received a reset conf!\n", __func__); break; default: - if (ev->cfm_prim) { + if (ev->cfm_prim) printk(KERN_INFO "%s: received unknown %d prim!\n", __func__, ev->cfm_prim); - break; - } - goto out_skb_put; /* No confirmation */ + /* No confirmation */ + break; } -out_kfree_skb: - kfree_skb(skb); out_skb_put: kfree_skb(skb); return rc; } -int llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) +void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) { /* queue PDU to send to MAC layer */ skb_queue_tail(&sk->sk_write_queue, skb); - return llc_conn_send_pdus(sk, skb); + llc_conn_send_pdus(sk); } /** @@ -255,7 +236,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit) if (howmany_resend > 0) llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO; /* any PDUs to re-send are queued up; start sending to MAC */ - llc_conn_send_pdus(sk, NULL); + llc_conn_send_pdus(sk); out:; } @@ -296,7 +277,7 @@ void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit) if (howmany_resend > 0) llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO; /* any PDUs to re-send are queued up; start sending to MAC */ - llc_conn_send_pdus(sk, NULL); + llc_conn_send_pdus(sk); out:; } @@ -340,16 +321,12 @@ int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked) /** * llc_conn_send_pdus - Sends queued PDUs * @sk: active connection - * @hold_skb: the skb held by caller, or NULL if does not care * - * Sends queued pdus to MAC layer for transmission. When @hold_skb is - * NULL, always return 0. Otherwise, return 0 if @hold_skb is sent - * successfully, or 1 for failure. + * Sends queued pdus to MAC layer for transmission. */ -static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *hold_skb) +static void llc_conn_send_pdus(struct sock *sk) { struct sk_buff *skb; - int ret = 0; while ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL) { struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); @@ -361,20 +338,10 @@ static int llc_conn_send_pdus(struct sock *sk, struct sk_buff *hold_skb) skb_queue_tail(&llc_sk(sk)->pdu_unack_q, skb); if (!skb2) break; - dev_queue_xmit(skb2); - } else { - bool is_target = skb == hold_skb; - int rc; - - if (is_target) - skb_get(skb); - rc = dev_queue_xmit(skb); - if (is_target) - ret = rc; + skb = skb2; } + dev_queue_xmit(skb); } - - return ret; } /** @@ -846,7 +813,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) else { dprintk("%s: adding to backlog...\n", __func__); llc_set_backlog_type(skb, LLC_PACKET); - if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) + if (sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf))) goto drop_unlock; } out: diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c index 8db03c2d5440b12536b3b7016bc5c01b56666d8a..ad6547736c219dafe42c2014257c0c87f372934f 100644 --- a/net/llc/llc_if.c +++ b/net/llc/llc_if.c @@ -38,6 +38,8 @@ * closed and -EBUSY when sending data is not permitted in this state or * LLC has send an I pdu with p bit set to 1 and is waiting for it's * response. + * + * This function always consumes a reference to the skb. */ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) { @@ -46,20 +48,22 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) struct llc_sock *llc = llc_sk(sk); if (unlikely(llc->state == LLC_CONN_STATE_ADM)) - goto out; + goto out_free; rc = -EBUSY; if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */ llc->p_flag)) { llc->failed_data_req = 1; - goto out; + goto out_free; } ev = llc_conn_ev(skb); ev->type = LLC_CONN_EV_TYPE_PRIM; ev->prim = LLC_DATA_PRIM; ev->prim_type = LLC_PRIM_TYPE_REQ; skb->dev = llc->dev; - rc = llc_conn_state_process(sk, skb); -out: + return llc_conn_state_process(sk, skb); + +out_free: + kfree_skb(skb); return rc; } diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c index a94bd56bcac6f74110a0f231814fb45f4a600f30..7ae4cc684d3abe351a72110f3041ebe003063d26 100644 --- a/net/llc/llc_s_ac.c +++ b/net/llc/llc_s_ac.c @@ -58,8 +58,10 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_ui_cmd(skb); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (likely(!rc)) + if (likely(!rc)) { + skb_get(skb); rc = dev_queue_xmit(skb); + } return rc; } @@ -81,8 +83,10 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (likely(!rc)) + if (likely(!rc)) { + skb_get(skb); rc = dev_queue_xmit(skb); + } return rc; } @@ -135,8 +139,10 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_test_cmd(skb); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (likely(!rc)) + if (likely(!rc)) { + skb_get(skb); rc = dev_queue_xmit(skb); + } return rc; } diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index a7f7b8ff47292b476b4e3ec2e17e05a6fa0ee3ca..be419062e19a605f198585e56ef20a7da8774187 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -197,29 +197,22 @@ static int llc_sap_next_state(struct llc_sap *sap, struct sk_buff *skb) * After executing actions of the event, upper layer will be indicated * if needed(on receiving an UI frame). sk can be null for the * datalink_proto case. + * + * This function always consumes a reference to the skb. */ static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb) { struct llc_sap_state_ev *ev = llc_sap_ev(skb); - /* - * We have to hold the skb, because llc_sap_next_state - * will kfree it in the sending path and we need to - * look at the skb->cb, where we encode llc_sap_state_ev. - */ - skb_get(skb); ev->ind_cfm_flag = 0; llc_sap_next_state(sap, skb); - if (ev->ind_cfm_flag == LLC_IND) { - if (skb->sk->sk_state == TCP_LISTEN) - kfree_skb(skb); - else { - llc_save_primitive(skb->sk, skb, ev->prim); - /* queue skb to the user. */ - if (sock_queue_rcv_skb(skb->sk, skb)) - kfree_skb(skb); - } + if (ev->ind_cfm_flag == LLC_IND && skb->sk->sk_state != TCP_LISTEN) { + llc_save_primitive(skb->sk, skb, ev->prim); + + /* queue skb to the user. */ + if (sock_queue_rcv_skb(skb->sk, skb) == 0) + return; } kfree_skb(skb); } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 26a2f49208b6a30623667f21dfb0b18fd7aba2d2..54dd8849d1cc7dd25117f3fab41f286fb4b70f14 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2633,7 +2633,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, rcu_read_lock(); ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); - if (WARN_ON_ONCE(ssid == NULL)) + if (WARN_ONCE(!ssid || ssid[1] > IEEE80211_MAX_SSID_LEN, + "invalid SSID element (len=%d)", ssid ? ssid[1] : -1)) ssid_len = 0; else ssid_len = ssid[1]; @@ -5233,7 +5234,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); - if (!ssidie) { + if (!ssidie || ssidie[1] > sizeof(assoc_data->ssid)) { rcu_read_unlock(); kfree(assoc_data); return -EINVAL; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 768d14c9a7161c56c78d11253bb6e152c999ecdb..0e05ff0376726ddbaf80f05d9f90f6f086225b88 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3467,9 +3467,18 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): /* process for all: mesh, mlme, ibss */ break; + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + if (is_multicast_ether_addr(mgmt->da) && + !is_broadcast_ether_addr(mgmt->da)) + return RX_DROP_MONITOR; + + /* process only for station/IBSS */ + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) + return RX_DROP_MONITOR; + break; case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): case cpu_to_le16(IEEE80211_STYPE_DISASSOC): if (is_multicast_ether_addr(mgmt->da) && !is_broadcast_ether_addr(mgmt->da)) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index adf94ba1ed77a5c44ae8479541d03c63466c62ab..4d31d9688dc230275c49b34c876b36ad2b635a1b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -520,10 +520,33 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local, return 0; } +static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *sdata_iter; + + if (!ieee80211_is_radar_required(local)) + return true; + + if (!regulatory_pre_cac_allowed(local->hw.wiphy)) + return false; + + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata_iter, &local->interfaces, list) { + if (sdata_iter->wdev.cac_started) { + mutex_unlock(&local->iflist_mtx); + return false; + } + } + mutex_unlock(&local->iflist_mtx); + + return true; +} + static bool ieee80211_can_scan(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) { - if (ieee80211_is_radar_required(local)) + if (!__ieee80211_can_leave_ch(sdata)) return false; if (!list_empty(&local->roc_list)) @@ -630,7 +653,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, lockdep_assert_held(&local->mtx); - if (local->scan_req || ieee80211_is_radar_required(local)) + if (local->scan_req) + return -EBUSY; + + if (!__ieee80211_can_leave_ch(sdata)) return -EBUSY; if (!ieee80211_can_scan(local, sdata)) { diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 4515056ef1c2b4d7ab268986152bc6845b006fbd..f9b16f2b221918f1be0ae6bd8da118b2046670a2 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c @@ -193,21 +193,29 @@ struct ip_vs_app *register_ip_vs_app(struct netns_ipvs *ipvs, struct ip_vs_app * mutex_lock(&__ip_vs_app_mutex); + /* increase the module use count */ + if (!ip_vs_use_count_inc()) { + err = -ENOENT; + goto out_unlock; + } + list_for_each_entry(a, &ipvs->app_list, a_list) { if (!strcmp(app->name, a->name)) { err = -EEXIST; + /* decrease the module use count */ + ip_vs_use_count_dec(); goto out_unlock; } } a = kmemdup(app, sizeof(*app), GFP_KERNEL); if (!a) { err = -ENOMEM; + /* decrease the module use count */ + ip_vs_use_count_dec(); goto out_unlock; } INIT_LIST_HEAD(&a->incs_list); list_add(&a->a_list, &ipvs->app_list); - /* increase the module use count */ - ip_vs_use_count_inc(); out_unlock: mutex_unlock(&__ip_vs_app_mutex); diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 8b48e7ce1c2c2243bbdc8c4e43e4e484f3e52df6..3cccc88ef817bdbc4719316757e8cf8b5d61df1b 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -93,7 +93,6 @@ static bool __ip_vs_addr_is_local_v6(struct net *net, static void update_defense_level(struct netns_ipvs *ipvs) { struct sysinfo i; - static int old_secure_tcp = 0; int availmem; int nomem; int to_change = -1; @@ -174,35 +173,35 @@ static void update_defense_level(struct netns_ipvs *ipvs) spin_lock(&ipvs->securetcp_lock); switch (ipvs->sysctl_secure_tcp) { case 0: - if (old_secure_tcp >= 2) + if (ipvs->old_secure_tcp >= 2) to_change = 0; break; case 1: if (nomem) { - if (old_secure_tcp < 2) + if (ipvs->old_secure_tcp < 2) to_change = 1; ipvs->sysctl_secure_tcp = 2; } else { - if (old_secure_tcp >= 2) + if (ipvs->old_secure_tcp >= 2) to_change = 0; } break; case 2: if (nomem) { - if (old_secure_tcp < 2) + if (ipvs->old_secure_tcp < 2) to_change = 1; } else { - if (old_secure_tcp >= 2) + if (ipvs->old_secure_tcp >= 2) to_change = 0; ipvs->sysctl_secure_tcp = 1; } break; case 3: - if (old_secure_tcp < 2) + if (ipvs->old_secure_tcp < 2) to_change = 1; break; } - old_secure_tcp = ipvs->sysctl_secure_tcp; + ipvs->old_secure_tcp = ipvs->sysctl_secure_tcp; if (to_change >= 0) ip_vs_protocol_timeout_change(ipvs, ipvs->sysctl_secure_tcp > 1); @@ -1275,7 +1274,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, struct ip_vs_service *svc = NULL; /* increase the module use count */ - ip_vs_use_count_inc(); + if (!ip_vs_use_count_inc()) + return -ENOPROTOOPT; /* Lookup the scheduler by 'u->sched_name' */ if (strcmp(u->sched_name, "none")) { @@ -2435,9 +2435,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) if (copy_from_user(arg, user, len) != 0) return -EFAULT; - /* increase the module use count */ - ip_vs_use_count_inc(); - /* Handle daemons since they have another lock */ if (cmd == IP_VS_SO_SET_STARTDAEMON || cmd == IP_VS_SO_SET_STOPDAEMON) { @@ -2450,13 +2447,13 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ret = -EINVAL; if (strscpy(cfg.mcast_ifn, dm->mcast_ifn, sizeof(cfg.mcast_ifn)) <= 0) - goto out_dec; + return ret; cfg.syncid = dm->syncid; ret = start_sync_thread(ipvs, &cfg, dm->state); } else { ret = stop_sync_thread(ipvs, dm->state); } - goto out_dec; + return ret; } mutex_lock(&__ip_vs_mutex); @@ -2551,10 +2548,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) out_unlock: mutex_unlock(&__ip_vs_mutex); - out_dec: - /* decrease the module use count */ - ip_vs_use_count_dec(); - return ret; } diff --git a/net/netfilter/ipvs/ip_vs_pe.c b/net/netfilter/ipvs/ip_vs_pe.c index 8e104dff7abc414c3879a5a7555814badf44b8e4..166c669f07634b2652e8ed71938415de20b9a14f 100644 --- a/net/netfilter/ipvs/ip_vs_pe.c +++ b/net/netfilter/ipvs/ip_vs_pe.c @@ -68,7 +68,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe) struct ip_vs_pe *tmp; /* increase the module use count */ - ip_vs_use_count_inc(); + if (!ip_vs_use_count_inc()) + return -ENOENT; mutex_lock(&ip_vs_pe_mutex); /* Make sure that the pe with this name doesn't exist diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c index 2f9d5cd5daeeeb842fc174cb47612a1e81d202fe..d4903723be7e90ad6c996f00ee66486acd6302fb 100644 --- a/net/netfilter/ipvs/ip_vs_sched.c +++ b/net/netfilter/ipvs/ip_vs_sched.c @@ -179,7 +179,8 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) } /* increase the module use count */ - ip_vs_use_count_inc(); + if (!ip_vs_use_count_inc()) + return -ENOENT; mutex_lock(&ip_vs_sched_mutex); diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index a4a78c4b06dec380dc4db957f9c95cf050998580..8dc892a9dc91a9bbd0b11bf53c3da506de548fd2 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -1762,6 +1762,10 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %zd bytes\n", sizeof(struct ip_vs_sync_conn_v0)); + /* increase the module use count */ + if (!ip_vs_use_count_inc()) + return -ENOPROTOOPT; + /* Do not hold one mutex and then to block on another */ for (;;) { rtnl_lock(); @@ -1892,9 +1896,6 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, mutex_unlock(&ipvs->sync_mutex); rtnl_unlock(); - /* increase the module use count */ - ip_vs_use_count_inc(); - return 0; out: @@ -1924,11 +1925,17 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c, } kfree(ti); } + + /* decrease the module use count */ + ip_vs_use_count_dec(); return result; out_early: mutex_unlock(&ipvs->sync_mutex); rtnl_unlock(); + + /* decrease the module use count */ + ip_vs_use_count_dec(); return result; } diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0c63120b2db2e1ea9983a6b1ce8d2aefebc29501..5cd610b547e0d1e3463a65ba3627f265c836bdc5 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1792,8 +1792,8 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, if (nf_ct_is_confirmed(ct)) extra_jiffies += nfct_time_stamp; - if (ct->timeout != extra_jiffies) - ct->timeout = extra_jiffies; + if (READ_ONCE(ct->timeout) != extra_jiffies) + WRITE_ONCE(ct->timeout, extra_jiffies); acct: if (do_acct) nf_ct_acct_update(ct, ctinfo, skb->len); diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c index 132f5228b4319df1f584d69f0ff75f40c45dad28..128245efe84abec57723f2c26262c90d7b3e27e8 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c @@ -202,6 +202,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) { int err; + flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; + err = rhashtable_insert_fast(&flow_table->rhashtable, &flow->tuplehash[0].node, nf_flow_offload_rhash_params); @@ -218,7 +220,6 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) return err; } - flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; return 0; } EXPORT_SYMBOL_GPL(flow_offload_add); diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index e546f759b7a714b5376c035e1a82cc1821cb680e..ad783f4840efea23e04cd1d2bd438da274124c9c 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -347,7 +347,7 @@ int nft_flow_rule_offload_commit(struct net *net) policy = nft_trans_chain_policy(trans); err = nft_flow_offload_chain(trans->ctx.chain, &policy, - FLOW_BLOCK_BIND); + FLOW_BLOCK_UNBIND); break; case NFT_MSG_NEWRULE: if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)) diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 22a80eb60222ef06b671b0b1cbea87609a71786e..5cb2d8908d2a5d47bdedcaaf3383636708b366fc 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -161,13 +161,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx, switch (priv->offset) { case offsetof(struct ethhdr, h_source): + if (priv->len != ETH_ALEN) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, src, ETH_ALEN, reg); break; case offsetof(struct ethhdr, h_dest): + if (priv->len != ETH_ALEN) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, dst, ETH_ALEN, reg); break; + default: + return -EOPNOTSUPP; } return 0; @@ -181,14 +189,23 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx, switch (priv->offset) { case offsetof(struct iphdr, saddr): + if (priv->len != sizeof(struct in_addr)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src, sizeof(struct in_addr), reg); break; case offsetof(struct iphdr, daddr): + if (priv->len != sizeof(struct in_addr)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst, sizeof(struct in_addr), reg); break; case offsetof(struct iphdr, protocol): + if (priv->len != sizeof(__u8)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, sizeof(__u8), reg); nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); @@ -208,14 +225,23 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx, switch (priv->offset) { case offsetof(struct ipv6hdr, saddr): + if (priv->len != sizeof(struct in6_addr)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src, sizeof(struct in6_addr), reg); break; case offsetof(struct ipv6hdr, daddr): + if (priv->len != sizeof(struct in6_addr)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst, sizeof(struct in6_addr), reg); break; case offsetof(struct ipv6hdr, nexthdr): + if (priv->len != sizeof(__u8)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, sizeof(__u8), reg); nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); @@ -255,10 +281,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx, switch (priv->offset) { case offsetof(struct tcphdr, source): + if (priv->len != sizeof(__be16)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, sizeof(__be16), reg); break; case offsetof(struct tcphdr, dest): + if (priv->len != sizeof(__be16)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, sizeof(__be16), reg); break; @@ -277,10 +309,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx, switch (priv->offset) { case offsetof(struct udphdr, source): + if (priv->len != sizeof(__be16)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, sizeof(__be16), reg); break; case offsetof(struct udphdr, dest): + if (priv->len != sizeof(__be16)) + return -EOPNOTSUPP; + NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, sizeof(__be16), reg); break; diff --git a/net/netfilter/xt_quota2.c b/net/netfilter/xt_quota2.c index 24b774263aa6aa9a800e0f3c46c381e3ddcc165c..c42724469759b8742cff4354b38b473621a572bd 100644 --- a/net/netfilter/xt_quota2.c +++ b/net/netfilter/xt_quota2.c @@ -296,8 +296,8 @@ static void quota_mt2_destroy(const struct xt_mtdtor_param *par) } list_del(&e->list); - remove_proc_entry(e->name, proc_xt_quota); spin_unlock_bh(&counter_list_lock); + remove_proc_entry(e->name, proc_xt_quota); kfree(e); } diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index c4f54ad2b98afb44002415ce1daf2afef646d8c0..58d5373c513c7999bd73813eafd80c8abad87dc4 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -63,28 +63,6 @@ static DEFINE_SPINLOCK(nr_list_lock); static const struct proto_ops nr_proto_ops; -/* - * NETROM network devices are virtual network devices encapsulating NETROM - * frames into AX.25 which will be sent through an AX.25 device, so form a - * special "super class" of normal net devices; split their locks off into a - * separate class since they always nest. - */ -static struct lock_class_key nr_netdev_xmit_lock_key; -static struct lock_class_key nr_netdev_addr_lock_key; - -static void nr_set_lockdep_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, &nr_netdev_xmit_lock_key); -} - -static void nr_set_lockdep_key(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, &nr_netdev_addr_lock_key); - netdev_for_each_tx_queue(dev, nr_set_lockdep_one, NULL); -} - /* * Socket removal during an interrupt is now safe. */ @@ -1414,7 +1392,6 @@ static int __init nr_proto_init(void) free_netdev(dev); goto fail; } - nr_set_lockdep_key(dev); dev_nr[i] = dev; } diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index ccdd790e163a81d0be5c69842fb3d25a57c743c4..28604414dec1b7d03f0d175cc87c10e0922c7043 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -554,11 +554,11 @@ static __poll_t llcp_sock_poll(struct file *file, struct socket *sock, if (sk->sk_state == LLCP_LISTEN) return llcp_accept_poll(sk); - if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) + if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) mask |= EPOLLERR | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0); - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; if (sk->sk_state == LLCP_CLOSED) diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 3572e11b6f21ed09ab476d39b1c86bcfb15c5fa2..1c77f520f474d91e02c0c3460dbe6c707f9127c4 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -165,7 +165,8 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, { int err; - err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype); + err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype, + skb->mac_len); if (err) return err; @@ -178,7 +179,7 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key, { int err; - err = skb_mpls_pop(skb, ethertype); + err = skb_mpls_pop(skb, ethertype, skb->mac_len); if (err) return err; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index f30e406fbec5a321de0a489b2d41c39dd08fb561..d8c364d637b12d8ec6f1e30bb46a06b27cd06311 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -1881,7 +1881,7 @@ static struct genl_family dp_datapath_genl_family __ro_after_init = { /* Called with ovs_mutex or RCU read lock. */ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, struct net *net, u32 portid, u32 seq, - u32 flags, u8 cmd) + u32 flags, u8 cmd, gfp_t gfp) { struct ovs_header *ovs_header; struct ovs_vport_stats vport_stats; @@ -1902,7 +1902,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, goto nla_put_failure; if (!net_eq(net, dev_net(vport->dev))) { - int id = peernet2id_alloc(net, dev_net(vport->dev)); + int id = peernet2id_alloc(net, dev_net(vport->dev), gfp); if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id)) goto nla_put_failure; @@ -1943,11 +1943,12 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, struct net *net, struct sk_buff *skb; int retval; - skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!skb) return ERR_PTR(-ENOMEM); - retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd); + retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd, + GFP_KERNEL); BUG_ON(retval < 0); return skb; @@ -2089,7 +2090,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info) err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info), info->snd_portid, info->snd_seq, 0, - OVS_VPORT_CMD_NEW); + OVS_VPORT_CMD_NEW, GFP_KERNEL); new_headroom = netdev_get_fwd_headroom(vport->dev); @@ -2150,7 +2151,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info), info->snd_portid, info->snd_seq, 0, - OVS_VPORT_CMD_SET); + OVS_VPORT_CMD_SET, GFP_KERNEL); BUG_ON(err < 0); ovs_unlock(); @@ -2190,7 +2191,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info) err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info), info->snd_portid, info->snd_seq, 0, - OVS_VPORT_CMD_DEL); + OVS_VPORT_CMD_DEL, GFP_KERNEL); BUG_ON(err < 0); /* the vport deletion may trigger dp headroom update */ @@ -2237,7 +2238,7 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info) goto exit_unlock_free; err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info), info->snd_portid, info->snd_seq, 0, - OVS_VPORT_CMD_GET); + OVS_VPORT_CMD_GET, GFP_ATOMIC); BUG_ON(err < 0); rcu_read_unlock(); @@ -2273,7 +2274,8 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - OVS_VPORT_CMD_GET) < 0) + OVS_VPORT_CMD_GET, + GFP_ATOMIC) < 0) goto out; j++; diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 21c90d3a7ebf7233160467de97eec379467765a9..58a7b8312c28992ad96827d1eabea443f098a448 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -137,7 +137,7 @@ static void do_setup(struct net_device *netdev) netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH | IFF_NO_QUEUE; netdev->needs_free_netdev = true; - netdev->priv_destructor = internal_dev_destructor; + netdev->priv_destructor = NULL; netdev->ethtool_ops = &internal_dev_ethtool_ops; netdev->rtnl_link_ops = &internal_dev_link_ops; @@ -159,7 +159,6 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) struct internal_dev *internal_dev; struct net_device *dev; int err; - bool free_vport = true; vport = ovs_vport_alloc(0, &ovs_internal_vport_ops, parms); if (IS_ERR(vport)) { @@ -190,10 +189,9 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) rtnl_lock(); err = register_netdevice(vport->dev); - if (err) { - free_vport = false; + if (err) goto error_unlock; - } + vport->dev->priv_destructor = internal_dev_destructor; dev_set_promiscuity(vport->dev, 1); rtnl_unlock(); @@ -207,8 +205,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) error_free_netdev: free_netdev(dev); error_free_vport: - if (free_vport) - ovs_vport_free(vport); + ovs_vport_free(vport); error: return ERR_PTR(err); } diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 96ea9f254ae90ae957f800566b05a7f75d13948f..76d499f6af9ab32aa17422ef911497585b6649b7 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -338,9 +338,9 @@ static __poll_t pn_socket_poll(struct file *file, struct socket *sock, if (sk->sk_state == TCP_CLOSE) return EPOLLERR; - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; - if (!skb_queue_empty(&pn->ctrlreq_queue)) + if (!skb_queue_empty_lockless(&pn->ctrlreq_queue)) mask |= EPOLLPRI; if (!mask && sk->sk_state == TCP_CLOSE_WAIT) return EPOLLHUP; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index f0e9ccf472a970004bd4ea1adb4d758b926b5837..6a0df7c8a939e4976aa2815127885e127dd864fc 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -64,28 +64,6 @@ static const struct proto_ops rose_proto_ops; ax25_address rose_callsign; -/* - * ROSE network devices are virtual network devices encapsulating ROSE - * frames into AX.25 which will be sent through an AX.25 device, so form a - * special "super class" of normal net devices; split their locks off into a - * separate class since they always nest. - */ -static struct lock_class_key rose_netdev_xmit_lock_key; -static struct lock_class_key rose_netdev_addr_lock_key; - -static void rose_set_lockdep_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, &rose_netdev_xmit_lock_key); -} - -static void rose_set_lockdep_key(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, &rose_netdev_addr_lock_key); - netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL); -} - /* * Convert a ROSE address into text. */ @@ -1533,7 +1511,6 @@ static int __init rose_proto_init(void) free_netdev(dev); goto fail; } - rose_set_lockdep_key(dev); dev_rose[i] = dev; } diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 1091bf35a1992c8bdecbfcd2b8551f7316377133..7c7d10f2e0c181776611cd54d6048a17ed512d5f 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -556,6 +556,7 @@ struct rxrpc_call { struct rxrpc_peer *peer; /* Peer record for remote address */ struct rxrpc_sock __rcu *socket; /* socket responsible */ struct rxrpc_net *rxnet; /* Network namespace to which call belongs */ + const struct rxrpc_security *security; /* applied security module */ struct mutex user_mutex; /* User access mutex */ unsigned long ack_at; /* When deferred ACK needs to happen */ unsigned long ack_lost_at; /* When ACK is figured as lost */ @@ -600,6 +601,7 @@ struct rxrpc_call { int debug_id; /* debug ID for printks */ unsigned short rx_pkt_offset; /* Current recvmsg packet offset */ unsigned short rx_pkt_len; /* Current recvmsg packet len */ + bool rx_pkt_last; /* Current recvmsg packet is last */ /* Rx/Tx circular buffer, depending on phase. * diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c index 00c095d74145ddd8349bcb2efde2ae9c1d295f50..135bf5cd8dd51be0414ebb89975331d3f47d7b4e 100644 --- a/net/rxrpc/call_accept.c +++ b/net/rxrpc/call_accept.c @@ -84,7 +84,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, smp_store_release(&b->conn_backlog_head, (head + 1) & (size - 1)); - trace_rxrpc_conn(conn, rxrpc_conn_new_service, + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service, atomic_read(&conn->usage), here); } @@ -97,7 +97,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, call->flags |= (1 << RXRPC_CALL_IS_SERVICE); call->state = RXRPC_CALL_SERVER_PREALLOC; - trace_rxrpc_call(call, rxrpc_call_new_service, + trace_rxrpc_call(call->debug_id, rxrpc_call_new_service, atomic_read(&call->usage), here, (const void *)user_call_ID); @@ -307,6 +307,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx, rxrpc_see_call(call); call->conn = conn; + call->security = conn->security; call->peer = rxrpc_get_peer(conn->params.peer); call->cong_cwnd = call->peer->cong_cwnd; return call; diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 32d8dc677142db1b1920878cccb3de9c95b7b767..a31c18c09894d5dd55e7baccacd3c07e18d3b5fc 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -240,7 +240,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, if (p->intr) __set_bit(RXRPC_CALL_IS_INTR, &call->flags); call->tx_total_len = p->tx_total_len; - trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage), + trace_rxrpc_call(call->debug_id, rxrpc_call_new_client, + atomic_read(&call->usage), here, (const void *)p->user_call_ID); /* We need to protect a partially set up call against the user as we @@ -290,8 +291,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, if (ret < 0) goto error; - trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), - here, NULL); + trace_rxrpc_call(call->debug_id, rxrpc_call_connected, + atomic_read(&call->usage), here, NULL); rxrpc_start_call_timer(call); @@ -313,8 +314,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, error: __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, RX_CALL_DEAD, ret); - trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), - here, ERR_PTR(ret)); + trace_rxrpc_call(call->debug_id, rxrpc_call_error, + atomic_read(&call->usage), here, ERR_PTR(ret)); rxrpc_release_call(rx, call); mutex_unlock(&call->user_mutex); rxrpc_put_call(call, rxrpc_call_put); @@ -376,7 +377,8 @@ bool rxrpc_queue_call(struct rxrpc_call *call) if (n == 0) return false; if (rxrpc_queue_work(&call->processor)) - trace_rxrpc_call(call, rxrpc_call_queued, n + 1, here, NULL); + trace_rxrpc_call(call->debug_id, rxrpc_call_queued, n + 1, + here, NULL); else rxrpc_put_call(call, rxrpc_call_put_noqueue); return true; @@ -391,7 +393,8 @@ bool __rxrpc_queue_call(struct rxrpc_call *call) int n = atomic_read(&call->usage); ASSERTCMP(n, >=, 1); if (rxrpc_queue_work(&call->processor)) - trace_rxrpc_call(call, rxrpc_call_queued_ref, n, here, NULL); + trace_rxrpc_call(call->debug_id, rxrpc_call_queued_ref, n, + here, NULL); else rxrpc_put_call(call, rxrpc_call_put_noqueue); return true; @@ -406,7 +409,8 @@ void rxrpc_see_call(struct rxrpc_call *call) if (call) { int n = atomic_read(&call->usage); - trace_rxrpc_call(call, rxrpc_call_seen, n, here, NULL); + trace_rxrpc_call(call->debug_id, rxrpc_call_seen, n, + here, NULL); } } @@ -418,7 +422,7 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) const void *here = __builtin_return_address(0); int n = atomic_inc_return(&call->usage); - trace_rxrpc_call(call, op, n, here, NULL); + trace_rxrpc_call(call->debug_id, op, n, here, NULL); } /* @@ -445,7 +449,8 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); - trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage), + trace_rxrpc_call(call->debug_id, rxrpc_call_release, + atomic_read(&call->usage), here, (const void *)call->flags); ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); @@ -488,10 +493,10 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn); - if (conn) { + if (conn) rxrpc_disconnect_call(call); - conn->security->free_call_crypto(call); - } + if (call->security) + call->security->free_call_crypto(call); rxrpc_cleanup_ring(call); _leave(""); @@ -534,12 +539,13 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) { struct rxrpc_net *rxnet = call->rxnet; const void *here = __builtin_return_address(0); + unsigned int debug_id = call->debug_id; int n; ASSERT(call != NULL); n = atomic_dec_return(&call->usage); - trace_rxrpc_call(call, op, n, here, NULL); + trace_rxrpc_call(debug_id, op, n, here, NULL); ASSERTCMP(n, >=, 0); if (n == 0) { _debug("call %d dead", call->debug_id); diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index 3f1da1b49f690d0e3ccf6d93607cd2b0583d293b..376370cd9285252db965819427559ee07cc30c48 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c @@ -212,7 +212,8 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp) rxrpc_get_local(conn->params.local); key_get(conn->params.key); - trace_rxrpc_conn(conn, rxrpc_conn_new_client, atomic_read(&conn->usage), + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_client, + atomic_read(&conn->usage), __builtin_return_address(0)); trace_rxrpc_client(conn, -1, rxrpc_client_alloc); _leave(" = %p", conn); @@ -352,6 +353,7 @@ static int rxrpc_get_client_conn(struct rxrpc_sock *rx, if (cp->exclusive) { call->conn = candidate; + call->security = candidate->security; call->security_ix = candidate->security_ix; call->service_id = candidate->service_id; _leave(" = 0 [exclusive %d]", candidate->debug_id); @@ -403,6 +405,7 @@ static int rxrpc_get_client_conn(struct rxrpc_sock *rx, candidate_published: set_bit(RXRPC_CONN_IN_CLIENT_CONNS, &candidate->flags); call->conn = candidate; + call->security = candidate->security; call->security_ix = candidate->security_ix; call->service_id = candidate->service_id; spin_unlock(&local->client_conns_lock); @@ -425,6 +428,7 @@ static int rxrpc_get_client_conn(struct rxrpc_sock *rx, spin_lock(&conn->channel_lock); call->conn = conn; + call->security = conn->security; call->security_ix = conn->security_ix; call->service_id = conn->service_id; list_add_tail(&call->chan_wait_link, &conn->waiting_calls); @@ -985,11 +989,12 @@ rxrpc_put_one_client_conn(struct rxrpc_connection *conn) void rxrpc_put_client_conn(struct rxrpc_connection *conn) { const void *here = __builtin_return_address(0); + unsigned int debug_id = conn->debug_id; int n; do { n = atomic_dec_return(&conn->usage); - trace_rxrpc_conn(conn, rxrpc_conn_put_client, n, here); + trace_rxrpc_conn(debug_id, rxrpc_conn_put_client, n, here); if (n > 0) return; ASSERTCMP(n, >=, 0); diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index ed05b692213226e7494c3908caa4dcf44f39bf27..38d718e90dc69a35227ee80e9bf6704705a2e161 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c @@ -269,7 +269,7 @@ bool rxrpc_queue_conn(struct rxrpc_connection *conn) if (n == 0) return false; if (rxrpc_queue_work(&conn->processor)) - trace_rxrpc_conn(conn, rxrpc_conn_queued, n + 1, here); + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_queued, n + 1, here); else rxrpc_put_connection(conn); return true; @@ -284,7 +284,7 @@ void rxrpc_see_connection(struct rxrpc_connection *conn) if (conn) { int n = atomic_read(&conn->usage); - trace_rxrpc_conn(conn, rxrpc_conn_seen, n, here); + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_seen, n, here); } } @@ -296,7 +296,7 @@ void rxrpc_get_connection(struct rxrpc_connection *conn) const void *here = __builtin_return_address(0); int n = atomic_inc_return(&conn->usage); - trace_rxrpc_conn(conn, rxrpc_conn_got, n, here); + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n, here); } /* @@ -310,7 +310,7 @@ rxrpc_get_connection_maybe(struct rxrpc_connection *conn) if (conn) { int n = atomic_fetch_add_unless(&conn->usage, 1, 0); if (n > 0) - trace_rxrpc_conn(conn, rxrpc_conn_got, n + 1, here); + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n + 1, here); else conn = NULL; } @@ -333,10 +333,11 @@ static void rxrpc_set_service_reap_timer(struct rxrpc_net *rxnet, void rxrpc_put_service_conn(struct rxrpc_connection *conn) { const void *here = __builtin_return_address(0); + unsigned int debug_id = conn->debug_id; int n; n = atomic_dec_return(&conn->usage); - trace_rxrpc_conn(conn, rxrpc_conn_put_service, n, here); + trace_rxrpc_conn(debug_id, rxrpc_conn_put_service, n, here); ASSERTCMP(n, >=, 0); if (n == 1) rxrpc_set_service_reap_timer(conn->params.local->rxnet, @@ -420,7 +421,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work) */ if (atomic_cmpxchg(&conn->usage, 1, 0) != 1) continue; - trace_rxrpc_conn(conn, rxrpc_conn_reap_service, 0, NULL); + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_reap_service, 0, NULL); if (rxrpc_conn_is_client(conn)) BUG(); diff --git a/net/rxrpc/conn_service.c b/net/rxrpc/conn_service.c index b30e13f6d95fdf77689cd6b1491b114ddb1dc9ed..123d6ceab15cb0b00ccf65aec61370b64cda811b 100644 --- a/net/rxrpc/conn_service.c +++ b/net/rxrpc/conn_service.c @@ -134,7 +134,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn list_add_tail(&conn->proc_link, &rxnet->conn_proc_list); write_unlock(&rxnet->conn_lock); - trace_rxrpc_conn(conn, rxrpc_conn_new_service, + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service, atomic_read(&conn->usage), __builtin_return_address(0)); } diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index c97ebdc043e44525eaecdd54bc447c1895bdca74..48f67a9b1037ceb7b7a749a241bbb127a12a1f67 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c @@ -147,10 +147,16 @@ void rxrpc_error_report(struct sock *sk) { struct sock_exterr_skb *serr; struct sockaddr_rxrpc srx; - struct rxrpc_local *local = sk->sk_user_data; + struct rxrpc_local *local; struct rxrpc_peer *peer; struct sk_buff *skb; + rcu_read_lock(); + local = rcu_dereference_sk_user_data(sk); + if (unlikely(!local)) { + rcu_read_unlock(); + return; + } _enter("%p{%d}", sk, local->debug_id); /* Clear the outstanding error value on the socket so that it doesn't @@ -160,6 +166,7 @@ void rxrpc_error_report(struct sock *sk) skb = sock_dequeue_err_skb(sk); if (!skb) { + rcu_read_unlock(); _leave("UDP socket errqueue empty"); return; } @@ -167,11 +174,11 @@ void rxrpc_error_report(struct sock *sk) serr = SKB_EXT_ERR(skb); if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) { _leave("UDP empty message"); + rcu_read_unlock(); rxrpc_free_skb(skb, rxrpc_skb_freed); return; } - rcu_read_lock(); peer = rxrpc_lookup_peer_icmp_rcu(local, skb, &srx); if (peer && !rxrpc_get_peer_maybe(peer)) peer = NULL; diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c index 9c3ac96f71cbf8202ccdeca3af388ad8a2ae08b3..64830d8c1fdb5cf21497e89b812a18aa5fb9c143 100644 --- a/net/rxrpc/peer_object.c +++ b/net/rxrpc/peer_object.c @@ -216,7 +216,7 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp) peer = kzalloc(sizeof(struct rxrpc_peer), gfp); if (peer) { atomic_set(&peer->usage, 1); - peer->local = local; + peer->local = rxrpc_get_local(local); INIT_HLIST_HEAD(&peer->error_targets); peer->service_conns = RB_ROOT; seqlock_init(&peer->service_conn_lock); @@ -307,7 +307,6 @@ void rxrpc_new_incoming_peer(struct rxrpc_sock *rx, struct rxrpc_local *local, unsigned long hash_key; hash_key = rxrpc_peer_hash_key(local, &peer->srx); - peer->local = local; rxrpc_init_peer(rx, peer, hash_key); spin_lock(&rxnet->peer_hash_lock); @@ -382,7 +381,7 @@ struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer) int n; n = atomic_inc_return(&peer->usage); - trace_rxrpc_peer(peer, rxrpc_peer_got, n, here); + trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n, here); return peer; } @@ -396,7 +395,7 @@ struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *peer) if (peer) { int n = atomic_fetch_add_unless(&peer->usage, 1, 0); if (n > 0) - trace_rxrpc_peer(peer, rxrpc_peer_got, n + 1, here); + trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n + 1, here); else peer = NULL; } @@ -417,6 +416,7 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer) list_del_init(&peer->keepalive_link); spin_unlock_bh(&rxnet->peer_hash_lock); + rxrpc_put_local(peer->local); kfree_rcu(peer, rcu); } @@ -426,11 +426,13 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer) void rxrpc_put_peer(struct rxrpc_peer *peer) { const void *here = __builtin_return_address(0); + unsigned int debug_id; int n; if (peer) { + debug_id = peer->debug_id; n = atomic_dec_return(&peer->usage); - trace_rxrpc_peer(peer, rxrpc_peer_put, n, here); + trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here); if (n == 0) __rxrpc_put_peer(peer); } @@ -443,13 +445,15 @@ void rxrpc_put_peer(struct rxrpc_peer *peer) void rxrpc_put_peer_locked(struct rxrpc_peer *peer) { const void *here = __builtin_return_address(0); + unsigned int debug_id = peer->debug_id; int n; n = atomic_dec_return(&peer->usage); - trace_rxrpc_peer(peer, rxrpc_peer_put, n, here); + trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here); if (n == 0) { hash_del_rcu(&peer->hash_link); list_del_init(&peer->keepalive_link); + rxrpc_put_local(peer->local); kfree_rcu(peer, rcu); } } diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index 3b0becb1204156eff6753f2399ec09c40fd233b0..8578c39ec83959b99dc50fb00fb70968e09ad18e 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -251,8 +251,8 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb, seq += subpacket; } - return call->conn->security->verify_packet(call, skb, offset, len, - seq, cksum); + return call->security->verify_packet(call, skb, offset, len, + seq, cksum); } /* @@ -267,11 +267,13 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb, */ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb, u8 *_annotation, - unsigned int *_offset, unsigned int *_len) + unsigned int *_offset, unsigned int *_len, + bool *_last) { struct rxrpc_skb_priv *sp = rxrpc_skb(skb); unsigned int offset = sizeof(struct rxrpc_wire_header); unsigned int len; + bool last = false; int ret; u8 annotation = *_annotation; u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET; @@ -281,6 +283,8 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb, len = skb->len - offset; if (subpacket < sp->nr_subpackets - 1) len = RXRPC_JUMBO_DATALEN; + else if (sp->rx_flags & RXRPC_SKB_INCL_LAST) + last = true; if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) { ret = rxrpc_verify_packet(call, skb, annotation, offset, len); @@ -291,7 +295,8 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb, *_offset = offset; *_len = len; - call->conn->security->locate_data(call, skb, _offset, _len); + *_last = last; + call->security->locate_data(call, skb, _offset, _len); return 0; } @@ -309,7 +314,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, rxrpc_serial_t serial; rxrpc_seq_t hard_ack, top, seq; size_t remain; - bool last; + bool rx_pkt_last; unsigned int rx_pkt_offset, rx_pkt_len; int ix, copy, ret = -EAGAIN, ret2; @@ -319,6 +324,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, rx_pkt_offset = call->rx_pkt_offset; rx_pkt_len = call->rx_pkt_len; + rx_pkt_last = call->rx_pkt_last; if (call->state >= RXRPC_CALL_SERVER_ACK_REQUEST) { seq = call->rx_hard_ack; @@ -329,6 +335,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, /* Barriers against rxrpc_input_data(). */ hard_ack = call->rx_hard_ack; seq = hard_ack + 1; + while (top = smp_load_acquire(&call->rx_top), before_eq(seq, top) ) { @@ -356,7 +363,8 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, if (rx_pkt_offset == 0) { ret2 = rxrpc_locate_data(call, skb, &call->rxtx_annotations[ix], - &rx_pkt_offset, &rx_pkt_len); + &rx_pkt_offset, &rx_pkt_len, + &rx_pkt_last); trace_rxrpc_recvmsg(call, rxrpc_recvmsg_next, seq, rx_pkt_offset, rx_pkt_len, ret2); if (ret2 < 0) { @@ -396,13 +404,12 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, } /* The whole packet has been transferred. */ - last = sp->hdr.flags & RXRPC_LAST_PACKET; if (!(flags & MSG_PEEK)) rxrpc_rotate_rx_window(call); rx_pkt_offset = 0; rx_pkt_len = 0; - if (last) { + if (rx_pkt_last) { ASSERTCMP(seq, ==, READ_ONCE(call->rx_top)); ret = 1; goto out; @@ -415,6 +422,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, if (!(flags & MSG_PEEK)) { call->rx_pkt_offset = rx_pkt_offset; call->rx_pkt_len = rx_pkt_len; + call->rx_pkt_last = rx_pkt_last; } done: trace_rxrpc_recvmsg(call, rxrpc_recvmsg_data_return, seq, diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 6a1547b270fef519fc5c334ced74b728f6484d28..813fd68881429a8d8f029c2e819393f1f4d21b70 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -419,7 +419,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, call->tx_winsize) sp->hdr.flags |= RXRPC_MORE_PACKETS; - ret = conn->security->secure_packet( + ret = call->security->secure_packet( call, skb, skb->mark, skb->head); if (ret < 0) goto out; @@ -661,6 +661,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) case RXRPC_CALL_SERVER_PREALLOC: case RXRPC_CALL_SERVER_SECURING: case RXRPC_CALL_SERVER_ACCEPTING: + rxrpc_put_call(call, rxrpc_call_put); ret = -EBUSY; goto error_release_sock; default: diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 2558f00f6b3eda64a87f63c32592c15b7a0a2bfe..69d4676a402f54ac0d03999b5c73e572c1f06447 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -832,8 +832,7 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb) } static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = { - [TCA_ACT_KIND] = { .type = NLA_NUL_STRING, - .len = IFNAMSIZ - 1 }, + [TCA_ACT_KIND] = { .type = NLA_STRING }, [TCA_ACT_INDEX] = { .type = NLA_U32 }, [TCA_ACT_COOKIE] = { .type = NLA_BINARY, .len = TC_COOKIE_MAX_SIZE }, @@ -865,8 +864,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, NL_SET_ERR_MSG(extack, "TC action kind must be specified"); goto err_out; } - nla_strlcpy(act_name, kind, IFNAMSIZ); - + if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) { + NL_SET_ERR_MSG(extack, "TC action name too long"); + goto err_out; + } if (tb[TCA_ACT_COOKIE]) { cookie = nla_memdup_cookie(tb); if (!cookie) { @@ -1352,11 +1353,16 @@ static int tcf_action_add(struct net *net, struct nlattr *nla, struct netlink_ext_ack *extack) { size_t attr_size = 0; - int ret = 0; + int loop, ret; struct tc_action *actions[TCA_ACT_MAX_PRIO] = {}; - ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, actions, - &attr_size, true, extack); + for (loop = 0; loop < 10; loop++) { + ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, + actions, &attr_size, true, extack); + if (ret != -EAGAIN) + break; + } + if (ret < 0) return ret; ret = tcf_add_notify(net, n, actions, portid, attr_size, extack); @@ -1406,11 +1412,8 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, */ if (n->nlmsg_flags & NLM_F_REPLACE) ovr = 1; -replay: ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr, extack); - if (ret == -EAGAIN) - goto replay; break; case RTM_DELACTION: ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 9ce073a05414ae3289190446cb6cee057588f07d..08923b21e56607f4b163dafa4e2f97d348a34061 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -484,7 +484,11 @@ static int __init mirred_init_module(void) return err; pr_info("Mirror/redirect action on\n"); - return tcf_register_action(&act_mirred_ops, &mirred_net_ops); + err = tcf_register_action(&act_mirred_ops, &mirred_net_ops); + if (err) + unregister_netdevice_notifier(&mirred_device_notifier); + + return err; } static void __exit mirred_cleanup_module(void) diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c index e168df0e008acef81e579900602138b5da683111..4cf6c553bb0bbf06376d4068c25775c1948cf065 100644 --- a/net/sched/act_mpls.c +++ b/net/sched/act_mpls.c @@ -55,7 +55,7 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a, struct tcf_mpls *m = to_mpls(a); struct tcf_mpls_params *p; __be32 new_lse; - int ret; + int ret, mac_len; tcf_lastuse_update(&m->tcf_tm); bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb); @@ -63,8 +63,12 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a, /* Ensure 'data' points at mac_header prior calling mpls manipulating * functions. */ - if (skb_at_tc_ingress(skb)) + if (skb_at_tc_ingress(skb)) { skb_push_rcsum(skb, skb->mac_len); + mac_len = skb->mac_len; + } else { + mac_len = skb_network_header(skb) - skb_mac_header(skb); + } ret = READ_ONCE(m->tcf_action); @@ -72,12 +76,12 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a, switch (p->tcfm_action) { case TCA_MPLS_ACT_POP: - if (skb_mpls_pop(skb, p->tcfm_proto)) + if (skb_mpls_pop(skb, p->tcfm_proto, mac_len)) goto drop; break; case TCA_MPLS_ACT_PUSH: new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb->protocol)); - if (skb_mpls_push(skb, new_lse, p->tcfm_proto)) + if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len)) goto drop; break; case TCA_MPLS_ACT_MODIFY: diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 64584a1df42548427014d98c4c8e088aa5351a6f..8717c0b26c905457e5b220465cceb2ffae71e561 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -162,11 +162,22 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp) return TC_H_MAJ(first); } +static bool tcf_proto_check_kind(struct nlattr *kind, char *name) +{ + if (kind) + return nla_strlcpy(name, kind, IFNAMSIZ) >= IFNAMSIZ; + memset(name, 0, IFNAMSIZ); + return false; +} + static bool tcf_proto_is_unlocked(const char *kind) { const struct tcf_proto_ops *ops; bool ret; + if (strlen(kind) == 0) + return false; + ops = tcf_proto_lookup_ops(kind, false, NULL); /* On error return false to take rtnl lock. Proto lookup/create * functions will perform lookup again and properly handle errors. @@ -1843,6 +1854,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, { struct net *net = sock_net(skb->sk); struct nlattr *tca[TCA_MAX + 1]; + char name[IFNAMSIZ]; struct tcmsg *t; u32 protocol; u32 prio; @@ -1899,13 +1911,19 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, if (err) return err; + if (tcf_proto_check_kind(tca[TCA_KIND], name)) { + NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); + err = -EINVAL; + goto errout; + } + /* Take rtnl mutex if rtnl_held was set to true on previous iteration, * block is shared (no qdisc found), qdisc is not unlocked, classifier * type is not specified, classifier is not unlocked. */ if (rtnl_held || (q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || - !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { + !tcf_proto_is_unlocked(name)) { rtnl_held = true; rtnl_lock(); } @@ -2063,6 +2081,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, { struct net *net = sock_net(skb->sk); struct nlattr *tca[TCA_MAX + 1]; + char name[IFNAMSIZ]; struct tcmsg *t; u32 protocol; u32 prio; @@ -2102,13 +2121,18 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, if (err) return err; + if (tcf_proto_check_kind(tca[TCA_KIND], name)) { + NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); + err = -EINVAL; + goto errout; + } /* Take rtnl mutex if flushing whole chain, block is shared (no qdisc * found), qdisc is not unlocked, classifier type is not specified, * classifier is not unlocked. */ if (!prio || (q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || - !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { + !tcf_proto_is_unlocked(name)) { rtnl_held = true; rtnl_lock(); } @@ -2216,6 +2240,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, { struct net *net = sock_net(skb->sk); struct nlattr *tca[TCA_MAX + 1]; + char name[IFNAMSIZ]; struct tcmsg *t; u32 protocol; u32 prio; @@ -2252,12 +2277,17 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, if (err) return err; + if (tcf_proto_check_kind(tca[TCA_KIND], name)) { + NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); + err = -EINVAL; + goto errout; + } /* Take rtnl mutex if block is shared (no qdisc found), qdisc is not * unlocked, classifier type is not specified, classifier is not * unlocked. */ if ((q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || - !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { + !tcf_proto_is_unlocked(name)) { rtnl_held = true; rtnl_lock(); } diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index bf10bdaf5012734012b34a30e0d31faebcbeed21..8229ed4a67bee6eaa46cd365f202b6e698b1d7a9 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -162,16 +162,20 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, cls_bpf.name = obj->bpf_name; cls_bpf.exts_integrated = obj->exts_integrated; - if (oldprog) + if (oldprog && prog) err = tc_setup_cb_replace(block, tp, TC_SETUP_CLSBPF, &cls_bpf, skip_sw, &oldprog->gen_flags, &oldprog->in_hw_count, &prog->gen_flags, &prog->in_hw_count, true); - else + else if (prog) err = tc_setup_cb_add(block, tp, TC_SETUP_CLSBPF, &cls_bpf, skip_sw, &prog->gen_flags, &prog->in_hw_count, true); + else + err = tc_setup_cb_destroy(block, tp, TC_SETUP_CLSBPF, &cls_bpf, + skip_sw, &oldprog->gen_flags, + &oldprog->in_hw_count, true); if (prog && err) { cls_bpf_offload_cmd(tp, oldprog, prog, extack); diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 82bd14e7ac93dc709483b3437cdc1779b34d0888..3177dcb173161629a801278db38fabeb6fcdbdd9 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -446,7 +446,7 @@ META_COLLECTOR(int_sk_wmem_queued) *err = -1; return; } - dst->value = sk->sk_wmem_queued; + dst->value = READ_ONCE(sk->sk_wmem_queued); } META_COLLECTOR(int_sk_fwd_alloc) @@ -554,7 +554,7 @@ META_COLLECTOR(int_sk_rcvlowat) *err = -1; return; } - dst->value = sk->sk_rcvlowat; + dst->value = READ_ONCE(sk->sk_rcvlowat); } META_COLLECTOR(int_sk_rcvtimeo) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 81d58b28061221f6af6744080187489f674386ed..1047825d9f48d546fe1339a25f3f86979e7ac801 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1390,8 +1390,7 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w) } const struct nla_policy rtm_tca_policy[TCA_MAX + 1] = { - [TCA_KIND] = { .type = NLA_NUL_STRING, - .len = IFNAMSIZ - 1 }, + [TCA_KIND] = { .type = NLA_STRING }, [TCA_RATE] = { .type = NLA_BINARY, .len = sizeof(struct tc_estimator) }, [TCA_STAB] = { .type = NLA_NESTED }, diff --git a/net/sched/sch_etf.c b/net/sched/sch_etf.c index cebfb65d85568c3afa48c52d1f05887fd59b937b..b1da5589a0c6a2c9db9912430dca3d5f06fff10c 100644 --- a/net/sched/sch_etf.c +++ b/net/sched/sch_etf.c @@ -177,7 +177,7 @@ static int etf_enqueue_timesortedlist(struct sk_buff *nskb, struct Qdisc *sch, parent = *p; skb = rb_to_skb(parent); - if (ktime_after(txtime, skb->tstamp)) { + if (ktime_compare(txtime, skb->tstamp) >= 0) { p = &parent->rb_right; leftmost = false; } else { diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 17bd8f539bc7f1d596e97c713467f953802c9b82..8769b4b8807d9d6638619059230462750bdff2ee 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -799,9 +799,6 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = { }; EXPORT_SYMBOL(pfifo_fast_ops); -static struct lock_class_key qdisc_tx_busylock; -static struct lock_class_key qdisc_running_key; - struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, const struct Qdisc_ops *ops, struct netlink_ext_ack *extack) @@ -854,17 +851,9 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, } spin_lock_init(&sch->busylock); - lockdep_set_class(&sch->busylock, - dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); - /* seqlock has the same scope of busylock, for NOLOCK qdisc */ spin_lock_init(&sch->seqlock); - lockdep_set_class(&sch->busylock, - dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); - seqcount_init(&sch->running); - lockdep_set_class(&sch->running, - dev->qdisc_running_key ?: &qdisc_running_key); sch->ops = ops; sch->flags = ops->static_flags; @@ -875,6 +864,12 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, dev_hold(dev); refcount_set(&sch->refcnt, 1); + if (sch != &noop_qdisc) { + lockdep_set_class(&sch->busylock, &dev->qdisc_tx_busylock_key); + lockdep_set_class(&sch->seqlock, &dev->qdisc_tx_busylock_key); + lockdep_set_class(&sch->running, &dev->qdisc_running_key); + } + return sch; errout1: kfree(p); @@ -1043,6 +1038,8 @@ static void attach_one_default_qdisc(struct net_device *dev, if (dev->priv_flags & IFF_NO_QUEUE) ops = &noqueue_qdisc_ops; + else if(dev->type == ARPHRD_CAN) + ops = &pfifo_fast_ops; qdisc = qdisc_create_dflt(dev_queue, ops, TC_H_ROOT, NULL); if (!qdisc) { diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c index 23cd1c873a2cfc24b907a8177e71dd68b0939701..be35f03b657b1eb10d224594981aa44e1776801c 100644 --- a/net/sched/sch_hhf.c +++ b/net/sched/sch_hhf.c @@ -5,11 +5,11 @@ * Copyright (C) 2013 Nandita Dukkipati */ -#include #include #include #include #include +#include #include #include @@ -126,7 +126,7 @@ struct wdrr_bucket { struct hhf_sched_data { struct wdrr_bucket buckets[WDRR_BUCKET_CNT]; - u32 perturbation; /* hash perturbation */ + siphash_key_t perturbation; /* hash perturbation */ u32 quantum; /* psched_mtu(qdisc_dev(sch)); */ u32 drop_overlimit; /* number of times max qdisc packet * limit was hit @@ -264,7 +264,7 @@ static enum wdrr_bucket_idx hhf_classify(struct sk_buff *skb, struct Qdisc *sch) } /* Get hashed flow-id of the skb. */ - hash = skb_get_hash_perturb(skb, q->perturbation); + hash = skb_get_hash_perturb(skb, &q->perturbation); /* Check if this packet belongs to an already established HH flow. */ flow_pos = hash & HHF_BIT_MASK; @@ -582,7 +582,7 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt, sch->limit = 1000; q->quantum = psched_mtu(qdisc_dev(sch)); - q->perturbation = prandom_u32(); + get_random_bytes(&q->perturbation, sizeof(q->perturbation)); INIT_LIST_HEAD(&q->new_buckets); INIT_LIST_HEAD(&q->old_buckets); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 0e44039e729c72be52d0bf65568b3641e7f910d8..42e557d48e4e3f85ef9f6edc3c3bbe3c4df6eacd 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -509,6 +509,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) { qdisc_drop(skb, sch, to_free); + skb = NULL; goto finish_segs; } @@ -593,9 +594,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, finish_segs: if (segs) { unsigned int len, last_len; - int nb = 0; + int nb; - len = skb->len; + len = skb ? skb->len : 0; + nb = skb ? 1 : 0; while (segs) { skb2 = segs->next; @@ -612,7 +614,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, } segs = skb2; } - qdisc_tree_reduce_backlog(sch, -nb, prev_len - len); + /* Parent qdiscs accounted for 1 skb of size @prev_len */ + qdisc_tree_reduce_backlog(sch, -(nb - 1), -(len - prev_len)); + } else if (!skb) { + return NET_XMIT_DROP; } return NET_XMIT_SUCCESS; } diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index d448fe3068e5b9f0b35a37d921ab5a74350dc155..4074c50ac3d73100dd82bd631c127326ff49f355 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -45,7 +45,7 @@ struct sfb_bucket { * (Section 4.4 of SFB reference : moving hash functions) */ struct sfb_bins { - u32 perturbation; /* jhash perturbation */ + siphash_key_t perturbation; /* siphash key */ struct sfb_bucket bins[SFB_LEVELS][SFB_NUMBUCKETS]; }; @@ -217,7 +217,8 @@ static u32 sfb_compute_qlen(u32 *prob_r, u32 *avgpm_r, const struct sfb_sched_da static void sfb_init_perturbation(u32 slot, struct sfb_sched_data *q) { - q->bins[slot].perturbation = prandom_u32(); + get_random_bytes(&q->bins[slot].perturbation, + sizeof(q->bins[slot].perturbation)); } static void sfb_swap_slot(struct sfb_sched_data *q) @@ -314,9 +315,9 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch, /* If using external classifiers, get result and record it. */ if (!sfb_classify(skb, fl, &ret, &salt)) goto other_drop; - sfbhash = jhash_1word(salt, q->bins[slot].perturbation); + sfbhash = siphash_1u32(salt, &q->bins[slot].perturbation); } else { - sfbhash = skb_get_hash_perturb(skb, q->bins[slot].perturbation); + sfbhash = skb_get_hash_perturb(skb, &q->bins[slot].perturbation); } @@ -352,7 +353,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch, /* Inelastic flow */ if (q->double_buffering) { sfbhash = skb_get_hash_perturb(skb, - q->bins[slot].perturbation); + &q->bins[slot].perturbation); if (!sfbhash) sfbhash = 1; sfb_skb_cb(skb)->hashes[slot] = sfbhash; diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 68404a9d2ce426f7027d83f0adde634cb031ef4a..c787d4d46017b4b41b8eb6d41f2b0a44560ff5bf 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -117,7 +117,7 @@ struct sfq_sched_data { u8 headdrop; u8 maxdepth; /* limit of packets per flow */ - u32 perturbation; + siphash_key_t perturbation; u8 cur_depth; /* depth of longest slot */ u8 flags; unsigned short scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */ @@ -157,7 +157,7 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index static unsigned int sfq_hash(const struct sfq_sched_data *q, const struct sk_buff *skb) { - return skb_get_hash_perturb(skb, q->perturbation) & (q->divisor - 1); + return skb_get_hash_perturb(skb, &q->perturbation) & (q->divisor - 1); } static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, @@ -607,9 +607,11 @@ static void sfq_perturbation(struct timer_list *t) struct sfq_sched_data *q = from_timer(q, t, perturb_timer); struct Qdisc *sch = q->sch; spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch)); + siphash_key_t nkey; + get_random_bytes(&nkey, sizeof(nkey)); spin_lock(root_lock); - q->perturbation = prandom_u32(); + q->perturbation = nkey; if (!q->filter_list && q->tail) sfq_rehash(sch); spin_unlock(root_lock); @@ -688,7 +690,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) del_timer(&q->perturb_timer); if (q->perturb_period) { mod_timer(&q->perturb_timer, jiffies + q->perturb_period); - q->perturbation = prandom_u32(); + get_random_bytes(&q->perturbation, sizeof(q->perturbation)); } sch_tree_unlock(sch); kfree(p); @@ -745,7 +747,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt, q->quantum = psched_mtu(qdisc_dev(sch)); q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum); q->perturb_period = 0; - q->perturbation = prandom_u32(); + get_random_bytes(&q->perturbation, sizeof(q->perturbation)); if (opt) { int err = sfq_change(sch, opt); diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index 68b543f85a96b1065e040a53ca8778ce60f775cc..2121187229cd906c67e134d8ae78a65620f3296d 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -1152,7 +1152,7 @@ EXPORT_SYMBOL_GPL(taprio_offload_free); * offload state (PENDING, ACTIVE, INACTIVE) so it can be visible in dump(). * This is left as TODO. */ -void taprio_offload_config_changed(struct taprio_sched *q) +static void taprio_offload_config_changed(struct taprio_sched *q) { struct sched_gate_list *oper, *admin; @@ -1341,6 +1341,10 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb, NL_SET_ERR_MSG(extack, "Specifying a 'clockid' is mandatory"); goto out; } + + /* Everything went ok, return success. */ + err = 0; + out: return err; } diff --git a/net/sctp/diag.c b/net/sctp/diag.c index fc9a4c6629ce04b38b3882666ef0abbd5ea8705d..0851166b917597b08becf9bf9d5873287b375828 100644 --- a/net/sctp/diag.c +++ b/net/sctp/diag.c @@ -175,7 +175,7 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc, mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc; mem[SK_MEMINFO_WMEM_QUEUED] = sk->sk_wmem_queued; mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc); - mem[SK_MEMINFO_BACKLOG] = sk->sk_backlog.len; + mem[SK_MEMINFO_BACKLOG] = READ_ONCE(sk->sk_backlog.len); mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops); if (nla_put(skb, INET_DIAG_SKMEMINFO, sizeof(mem), &mem) < 0) diff --git a/net/sctp/input.c b/net/sctp/input.c index 5a070fb5b278f031339c8a239406ee0e019ff943..2277981559d0700669807dff4981e23e03be66ef 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -243,7 +243,7 @@ int sctp_rcv(struct sk_buff *skb) bh_lock_sock(sk); } - if (sock_owned_by_user(sk)) { + if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) { if (sctp_add_backlog(sk, skb)) { bh_unlock_sock(sk); sctp_chunk_free(chunk); @@ -321,8 +321,8 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) local_bh_disable(); bh_lock_sock(sk); - if (sock_owned_by_user(sk)) { - if (sk_add_backlog(sk, skb, sk->sk_rcvbuf)) + if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) { + if (sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf))) sctp_chunk_free(chunk); else backloged = 1; @@ -336,7 +336,13 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) if (backloged) return 0; } else { - sctp_inq_push(inqueue, chunk); + if (!sctp_newsk_ready(sk)) { + if (!sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf))) + return 0; + sctp_chunk_free(chunk); + } else { + sctp_inq_push(inqueue, chunk); + } } done: @@ -358,7 +364,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb) struct sctp_ep_common *rcvr = chunk->rcvr; int ret; - ret = sk_add_backlog(sk, skb, sk->sk_rcvbuf); + ret = sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf)); if (!ret) { /* Hold the assoc/ep while hanging on the backlog queue. * This way, we know structures we need will not disappear diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 939b8d2595bcafd45de7eb4116179dbf56547f2d..ffd3262b7a41eac2e3d825c3f0665066f376ea3c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -8476,7 +8476,7 @@ __poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait) mask = 0; /* Is there any exceptional events? */ - if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) + if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) mask |= EPOLLERR | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0); if (sk->sk_shutdown & RCV_SHUTDOWN) @@ -8485,7 +8485,7 @@ __poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait) mask |= EPOLLHUP; /* Is it readable? Reconsider this code with TCP-style support. */ - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; /* The association is either gone or not ready. */ @@ -8871,7 +8871,7 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, if (sk_can_busy_loop(sk)) { sk_busy_loop(sk, noblock); - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) continue; } @@ -9306,7 +9306,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, newinet->inet_rcv_saddr = inet->inet_rcv_saddr; newinet->inet_dport = htons(asoc->peer.port); newinet->pmtudisc = inet->pmtudisc; - newinet->inet_id = asoc->next_tsn ^ jiffies; + newinet->inet_id = prandom_u32(); newinet->uc_ttl = inet->uc_ttl; newinet->mc_loop = 1; @@ -9500,7 +9500,7 @@ struct proto sctp_prot = { .backlog_rcv = sctp_backlog_rcv, .hash = sctp_hash, .unhash = sctp_unhash, - .get_port = sctp_get_port, + .no_autobind = true, .obj_size = sizeof(struct sctp_sock), .useroffset = offsetof(struct sctp_sock, subscribe), .usersize = offsetof(struct sctp_sock, initmsg) - @@ -9542,7 +9542,7 @@ struct proto sctpv6_prot = { .backlog_rcv = sctp_backlog_rcv, .hash = sctp_hash, .unhash = sctp_unhash, - .get_port = sctp_get_port, + .no_autobind = true, .obj_size = sizeof(struct sctp6_sock), .useroffset = offsetof(struct sctp6_sock, sctp.subscribe), .usersize = offsetof(struct sctp6_sock, sctp.initmsg) - diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 5b932583e4076feacb786d315bc4d6181fd9a17b..47946f489fd4f4a7bfb771a4062d962b818670ca 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -123,6 +123,12 @@ struct proto smc_proto6 = { }; EXPORT_SYMBOL_GPL(smc_proto6); +static void smc_restore_fallback_changes(struct smc_sock *smc) +{ + smc->clcsock->file->private_data = smc->sk.sk_socket; + smc->clcsock->file = NULL; +} + static int __smc_release(struct smc_sock *smc) { struct sock *sk = &smc->sk; @@ -141,6 +147,7 @@ static int __smc_release(struct smc_sock *smc) } sk->sk_state = SMC_CLOSED; sk->sk_state_change(sk); + smc_restore_fallback_changes(smc); } sk->sk_prot->unhash(sk); @@ -700,8 +707,6 @@ static int __smc_connect(struct smc_sock *smc) int smc_type; int rc = 0; - sock_hold(&smc->sk); /* sock put in passive closing */ - if (smc->use_fallback) return smc_connect_fallback(smc, smc->fallback_rsn); @@ -846,6 +851,8 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr, rc = kernel_connect(smc->clcsock, addr, alen, flags); if (rc && rc != -EINPROGRESS) goto out; + + sock_hold(&smc->sk); /* sock put in passive closing */ if (flags & O_NONBLOCK) { if (schedule_work(&smc->connect_work)) smc->connect_nonblock = 1; @@ -1291,8 +1298,8 @@ static void smc_listen_work(struct work_struct *work) /* check if RDMA is available */ if (!ism_supported) { /* SMC_TYPE_R or SMC_TYPE_B */ /* prepare RDMA check */ - memset(&ini, 0, sizeof(ini)); ini.is_smcd = false; + ini.ism_dev = NULL; ini.ib_lcl = &pclc->lcl; rc = smc_find_rdma_device(new_smc, &ini); if (rc) { diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index 4ca50ddf8d1619a78e8a119ef2701d69957a8cd9..2ba97ff325a5d1eb90761ad47f1a8fa5d2f743d3 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -213,7 +213,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini) lgr = kzalloc(sizeof(*lgr), GFP_KERNEL); if (!lgr) { rc = SMC_CLC_DECL_MEM; - goto out; + goto ism_put_vlan; } lgr->is_smcd = ini->is_smcd; lgr->sync_err = 0; @@ -289,6 +289,9 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini) smc_llc_link_clear(lnk); free_lgr: kfree(lgr); +ism_put_vlan: + if (ini->is_smcd && ini->vlan_id) + smc_ism_put_vlan(ini->ism_dev, ini->vlan_id); out: if (rc < 0) { if (rc == -ENOMEM) @@ -558,7 +561,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini) } rtnl_lock(); - nest_lvl = dev_get_nest_level(ndev); + nest_lvl = ndev->lower_level; for (i = 0; i < nest_lvl; i++) { struct list_head *lower = &ndev->adj_list.lower; diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c index bab2da8cf17af875db0348a80b1d0488272f4990..2920b006f65c00f0f99a92e5625b895ad292fecd 100644 --- a/net/smc/smc_pnet.c +++ b/net/smc/smc_pnet.c @@ -718,7 +718,7 @@ static struct net_device *pnet_find_base_ndev(struct net_device *ndev) int i, nest_lvl; rtnl_lock(); - nest_lvl = dev_get_nest_level(ndev); + nest_lvl = ndev->lower_level; for (i = 0; i < nest_lvl; i++) { struct list_head *lower = &ndev->adj_list.lower; diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c index 413a6abf227ef13dacc8c6c20ccb92aa953a1bf0..97e8369002d71e970d4c01589cf9f671fddde6ea 100644 --- a/net/smc/smc_rx.c +++ b/net/smc/smc_rx.c @@ -211,8 +211,7 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo, rc = sk_wait_event(sk, timeo, sk->sk_err || sk->sk_shutdown & RCV_SHUTDOWN || - fcrit(conn) || - smc_cdc_rxed_any_close_or_senddone(conn), + fcrit(conn), &wait); remove_wait_queue(sk_sleep(sk), &wait); sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); @@ -262,6 +261,18 @@ static int smc_rx_recv_urg(struct smc_sock *smc, struct msghdr *msg, int len, return -EAGAIN; } +static bool smc_rx_recvmsg_data_available(struct smc_sock *smc) +{ + struct smc_connection *conn = &smc->conn; + + if (smc_rx_data_available(conn)) + return true; + else if (conn->urg_state == SMC_URG_VALID) + /* we received a single urgent Byte - skip */ + smc_rx_update_cons(smc, 0); + return false; +} + /* smc_rx_recvmsg - receive data from RMBE * @msg: copy data to receive buffer * @pipe: copy data to pipe if set - indicates splice() call @@ -303,16 +314,18 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, if (read_done >= target || (pipe && read_done)) break; - if (atomic_read(&conn->bytes_to_rcv)) + if (smc_rx_recvmsg_data_available(smc)) goto copy; - else if (conn->urg_state == SMC_URG_VALID) - /* we received a single urgent Byte - skip */ - smc_rx_update_cons(smc, 0); if (sk->sk_shutdown & RCV_SHUTDOWN || - smc_cdc_rxed_any_close_or_senddone(conn) || - conn->local_tx_ctrl.conn_state_flags.peer_conn_abort) + conn->local_tx_ctrl.conn_state_flags.peer_conn_abort) { + /* smc_cdc_msg_recv_action() could have run after + * above smc_rx_recvmsg_data_available() + */ + if (smc_rx_recvmsg_data_available(smc)) + goto copy; break; + } if (read_done) { if (sk->sk_err || diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 339e8c077c2db9dadf79e6498b2361c483753be3..195b40c5dae4ba8cb364c46d4631680b257bb7fa 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c @@ -220,7 +220,7 @@ void xprt_destroy_bc(struct rpc_xprt *xprt, unsigned int max_reqs) goto out; spin_lock_bh(&xprt->bc_pa_lock); - xprt->bc_alloc_max -= max_reqs; + xprt->bc_alloc_max -= min(max_reqs, xprt->bc_alloc_max); list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { dprintk("RPC: req=%p\n", req); list_del(&req->rq_bc_pa_list); @@ -307,8 +307,8 @@ void xprt_free_bc_rqst(struct rpc_rqst *req) */ dprintk("RPC: Last session removed req=%p\n", req); xprt_free_allocation(req); - return; } + xprt_put(xprt); } /* @@ -339,7 +339,7 @@ struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid) spin_unlock(&xprt->bc_pa_lock); if (new) { if (req != new) - xprt_free_bc_rqst(new); + xprt_free_allocation(new); break; } else if (req) break; @@ -368,6 +368,7 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); dprintk("RPC: add callback request to list\n"); + xprt_get(xprt); spin_lock(&bc_serv->sv_cb_lock); list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); wake_up(&bc_serv->sv_cb_waitq); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 8a45b3ccc31343aa089e9bed8837247256ecd61d..41df4c507193b39410f8c99f65c9fa0f795380c1 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1942,6 +1942,11 @@ static void xprt_destroy_cb(struct work_struct *work) rpc_destroy_wait_queue(&xprt->sending); rpc_destroy_wait_queue(&xprt->backlog); kfree(xprt->servername); + /* + * Destroy any existing back channel + */ + xprt_destroy_backchannel(xprt, UINT_MAX); + /* * Tear down transport state and free the rpc_xprt */ diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c index 50e075fcdd8feb13bc9747c613373e9b2570c073..b458bf53ca699adc271a790b7cb082af8aa31633 100644 --- a/net/sunrpc/xprtrdma/backchannel.c +++ b/net/sunrpc/xprtrdma/backchannel.c @@ -163,6 +163,7 @@ void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst) spin_lock(&xprt->bc_pa_lock); list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list); spin_unlock(&xprt->bc_pa_lock); + xprt_put(xprt); } static struct rpc_rqst *rpcrdma_bc_rqst_get(struct rpcrdma_xprt *r_xprt) @@ -259,6 +260,7 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt, /* Queue rqst for ULP's callback service */ bc_serv = xprt->bc_serv; + xprt_get(xprt); spin_lock(&bc_serv->sv_cb_lock); list_add(&rqst->rq_bc_list, &bc_serv->sv_cb_list); spin_unlock(&bc_serv->sv_cb_lock); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3b9f8cc328f5c3aa2f39b5a8267bd206e714835f..4b92b196cfa668c9ee59b9dae4e83bb7b5b5ba3d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -740,7 +740,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock, /* fall through */ case TIPC_LISTEN: case TIPC_CONNECTING: - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) revents |= EPOLLIN | EPOLLRDNORM; break; case TIPC_OPEN: @@ -748,7 +748,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock, revents |= EPOLLOUT; if (!tipc_sk_type_connectionless(sk)) break; - if (skb_queue_empty(&sk->sk_receive_queue)) + if (skb_queue_empty_lockless(&sk->sk_receive_queue)) break; revents |= EPOLLIN | EPOLLRDNORM; break; @@ -2119,13 +2119,13 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *skb) struct tipc_msg *hdr = buf_msg(skb); if (unlikely(msg_in_group(hdr))) - return sk->sk_rcvbuf; + return READ_ONCE(sk->sk_rcvbuf); if (unlikely(!msg_connected(hdr))) - return sk->sk_rcvbuf << msg_importance(hdr); + return READ_ONCE(sk->sk_rcvbuf) << msg_importance(hdr); if (likely(tsk->peer_caps & TIPC_BLOCK_FLOWCTL)) - return sk->sk_rcvbuf; + return READ_ONCE(sk->sk_rcvbuf); return FLOWCTL_MSG_LIM; } @@ -3790,7 +3790,7 @@ int tipc_sk_dump(struct sock *sk, u16 dqueues, char *buf) i += scnprintf(buf + i, sz - i, " %d", sk->sk_sndbuf); i += scnprintf(buf + i, sz - i, " | %d", sk_rmem_alloc_get(sk)); i += scnprintf(buf + i, sz - i, " %d", sk->sk_rcvbuf); - i += scnprintf(buf + i, sz - i, " | %d\n", sk->sk_backlog.len); + i += scnprintf(buf + i, sz - i, " | %d\n", READ_ONCE(sk->sk_backlog.len)); if (dqueues & TIPC_DUMP_SK_SNDQ) { i += scnprintf(buf + i, sz - i, "sk_write_queue: "); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 67e87db5877f1132b52b0c93d349983873fec38f..0d8da809bea2e6053c6bd5687ae19ab3f3ca617a 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2599,7 +2599,7 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM; /* readable? */ - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; /* Connection-based need to check for termination and startup */ @@ -2628,7 +2628,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock, mask = 0; /* exceptional events? */ - if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) + if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue)) mask |= EPOLLERR | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0); @@ -2638,7 +2638,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock, mask |= EPOLLHUP; /* readable? */ - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) mask |= EPOLLIN | EPOLLRDNORM; /* Connection-based need to check for termination and startup */ diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 2ab43b2bba31bca91de7fe7840c487e07683a922..582a3e4dfce295fa67100468335bc8dbf8dc1095 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -870,7 +870,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock, * the queue and write as long as the socket isn't shutdown for * sending. */ - if (!skb_queue_empty(&sk->sk_receive_queue) || + if (!skb_queue_empty_lockless(&sk->sk_receive_queue) || (sk->sk_shutdown & RCV_SHUTDOWN)) { mask |= EPOLLIN | EPOLLRDNORM; } diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index a666ef8fc54e17ce8e7827285f96f4a2bdc93004..481f7f8a16551ce8de4f6e3100464a32b0033997 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -204,10 +204,14 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, return virtio_transport_get_ops()->send_pkt(pkt); } -static void virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, +static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt) { + if (vvs->rx_bytes + pkt->len > vvs->buf_alloc) + return false; + vvs->rx_bytes += pkt->len; + return true; } static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs, @@ -458,6 +462,9 @@ void virtio_transport_set_buffer_size(struct vsock_sock *vsk, u64 val) vvs->buf_size_max = val; vvs->buf_size = val; vvs->buf_alloc = val; + + virtio_transport_send_credit_update(vsk, VIRTIO_VSOCK_TYPE_STREAM, + NULL); } EXPORT_SYMBOL_GPL(virtio_transport_set_buffer_size); @@ -876,14 +883,18 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk, struct virtio_vsock_pkt *pkt) { struct virtio_vsock_sock *vvs = vsk->trans; - bool free_pkt = false; + bool can_enqueue, free_pkt = false; pkt->len = le32_to_cpu(pkt->hdr.len); pkt->off = 0; spin_lock_bh(&vvs->rx_lock); - virtio_transport_inc_rx_pkt(vvs, pkt); + can_enqueue = virtio_transport_inc_rx_pkt(vvs, pkt); + if (!can_enqueue) { + free_pkt = true; + goto out; + } /* Try to copy small packets into the buffer of last packet queued, * to avoid wasting memory queueing the entire buffer with a small diff --git a/net/wireless/chan.c b/net/wireless/chan.c index e851cafd8e2f631fb4461676155ed9210eea8ec1..fcac5c6366e16d5d40e69a4cdc9378c7ba926528 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -204,6 +204,11 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) return false; } + /* channel 14 is only for IEEE 802.11b */ + if (chandef->center_freq1 == 2484 && + chandef->width != NL80211_CHAN_WIDTH_20_NOHT) + return false; + if (cfg80211_chandef_is_edmg(chandef) && !cfg80211_edmg_chandef_valid(chandef)) return false; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 141cdb171665e6b371c7d03818b46d17810ef912..7b72286922f7263acb9c0179d4110725a4311aba 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -393,7 +393,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ }, [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, .len = IEEE80211_MAX_MESH_ID_LEN }, - [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, + [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT, [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED }, @@ -13682,7 +13682,7 @@ static int nl80211_get_ftm_responder_stats(struct sk_buff *skb, hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, NL80211_CMD_GET_FTM_RESPONDER_STATS); if (!hdr) - return -ENOBUFS; + goto nla_put_failure; if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) goto nla_put_failure; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 420c4207ab59fa411039c2661c62a3af9e40098d..446c76d44e65a04878ceeaabda4f428e59e5b0f9 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -3883,6 +3883,7 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy) return pre_cac_allowed; } +EXPORT_SYMBOL(regulatory_pre_cac_allowed); void regulatory_propagate_dfs_state(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 504133d76de4de784dc7b2dccdac5a7ec11afbc0..dc8f689bd46902af8be9988283ebfaf18a1131d9 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -155,14 +155,6 @@ bool regulatory_indoor_allowed(void); */ #define REG_PRE_CAC_EXPIRY_GRACE_MS 2000 -/** - * regulatory_pre_cac_allowed - if pre-CAC allowed in the current dfs domain - * @wiphy: wiphy for which pre-CAC capability is checked. - - * Pre-CAC is allowed only in ETSI domain. - */ -bool regulatory_pre_cac_allowed(struct wiphy *wiphy); - /** * regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys * @wiphy - wiphy on which radar is detected and the event will be propagated diff --git a/net/wireless/scan.c b/net/wireless/scan.c index ff1016607f0b5cffb0fe92ef6982f5f5ddaaeae6..aef240fdf8df62dc9c15b515395db7c9ee4f1a18 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1703,8 +1703,7 @@ cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy, static void cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, struct cfg80211_bss *nontrans_bss, - struct ieee80211_mgmt *mgmt, size_t len, - gfp_t gfp) + struct ieee80211_mgmt *mgmt, size_t len) { u8 *ie, *new_ie, *pos; const u8 *nontrans_ssid, *trans_ssid, *mbssid; @@ -1715,6 +1714,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, const struct cfg80211_bss_ies *old; u8 cpy_len; + lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock); + ie = mgmt->u.probe_resp.variable; new_ie_len = ielen; @@ -1731,23 +1732,22 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, if (!mbssid || mbssid < trans_ssid) return; new_ie_len -= mbssid[1]; - rcu_read_lock(); + nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID); - if (!nontrans_ssid) { - rcu_read_unlock(); + if (!nontrans_ssid) return; - } + new_ie_len += nontrans_ssid[1]; - rcu_read_unlock(); /* generate new ie for nontrans BSS * 1. replace SSID with nontrans BSS' SSID * 2. skip MBSSID IE */ - new_ie = kzalloc(new_ie_len, gfp); + new_ie = kzalloc(new_ie_len, GFP_ATOMIC); if (!new_ie) return; - new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, gfp); + + new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC); if (!new_ies) goto out_free; @@ -1901,6 +1901,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len, &non_tx_data, gfp); + spin_lock_bh(&wiphy_to_rdev(wiphy)->bss_lock); + /* check if the res has other nontransmitting bss which is not * in MBSSID IE */ @@ -1915,8 +1917,9 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy, ies2 = rcu_access_pointer(tmp_bss->ies); if (ies2->tsf < ies1->tsf) cfg80211_update_notlisted_nontrans(wiphy, tmp_bss, - mgmt, len, gfp); + mgmt, len); } + spin_unlock_bh(&wiphy_to_rdev(wiphy)->bss_lock); return res; } diff --git a/net/wireless/util.c b/net/wireless/util.c index 419eb12c1e932d17f072b75288a7726c8b96da52..5b4ed5bbc542555a4ebd4e8fcfbb6dccf10e9f3f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1559,7 +1559,8 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, } if (freq == 2484) { - if (chandef->width > NL80211_CHAN_WIDTH_40) + /* channel 14 is only for IEEE 802.11b */ + if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) return false; *op_class = 82; /* channel 14 */ diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index c67d7a82ab132a50be6305f69df6576fd158a15e..73fd0eae08caa960eef0b72211c6fc2485cbfb43 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -202,6 +202,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, struct iw_point *data, char *ssid) { struct wireless_dev *wdev = dev->ieee80211_ptr; + int ret = 0; /* call only for station! */ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) @@ -219,7 +220,10 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, if (ie) { data->flags = 1; data->length = ie[1]; - memcpy(ssid, ie + 2, data->length); + if (data->length > IW_ESSID_MAX_SIZE) + ret = -EINVAL; + else + memcpy(ssid, ie + 2, data->length); } rcu_read_unlock(); } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { @@ -229,7 +233,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, } wdev_unlock(wdev); - return 0; + return ret; } int cfg80211_mgd_wext_siwap(struct net_device *dev, diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index 5c111bc3c8ea5a8c079cd0d83733e7b253d47158..00e782335cb0740daa172f0c1835bcc3285ba46b 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c @@ -55,7 +55,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) if (!sock_owned_by_user(sk)) { queued = x25_process_rx_frame(sk, skb); } else { - queued = !sk_add_backlog(sk, skb, sk->sk_rcvbuf); + queued = !sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf)); } bh_unlock_sock(sk); sock_put(sk); diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 16d5f353163a166dd4f29a8ae2b99aea63629c22..3049af269fbf6b3fc3fc0f8d40651ba39d187ed8 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -27,6 +27,9 @@ void xdp_add_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs) { unsigned long flags; + if (!xs->tx) + return; + spin_lock_irqsave(&umem->xsk_list_lock, flags); list_add_rcu(&xs->list, &umem->xsk_list); spin_unlock_irqrestore(&umem->xsk_list_lock, flags); @@ -36,6 +39,9 @@ void xdp_del_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs) { unsigned long flags; + if (!xs->tx) + return; + spin_lock_irqsave(&umem->xsk_list_lock, flags); list_del_rcu(&xs->list); spin_unlock_irqrestore(&umem->xsk_list_lock, flags); diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index fa8fbb8fa3c823aff9cb06d25f4335b662cc93c2..9044073fbf2257b0eb7632f05bc3b109d78604d8 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -305,9 +305,8 @@ bool xsk_umem_consume_tx(struct xdp_umem *umem, struct xdp_desc *desc) } EXPORT_SYMBOL(xsk_umem_consume_tx); -static int xsk_zc_xmit(struct sock *sk) +static int xsk_zc_xmit(struct xdp_sock *xs) { - struct xdp_sock *xs = xdp_sk(sk); struct net_device *dev = xs->dev; return dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, @@ -327,11 +326,10 @@ static void xsk_destruct_skb(struct sk_buff *skb) sock_wfree(skb); } -static int xsk_generic_xmit(struct sock *sk, struct msghdr *m, - size_t total_len) +static int xsk_generic_xmit(struct sock *sk) { - u32 max_batch = TX_BATCH_SIZE; struct xdp_sock *xs = xdp_sk(sk); + u32 max_batch = TX_BATCH_SIZE; bool sent_frame = false; struct xdp_desc desc; struct sk_buff *skb; @@ -394,6 +392,18 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m, return err; } +static int __xsk_sendmsg(struct sock *sk) +{ + struct xdp_sock *xs = xdp_sk(sk); + + if (unlikely(!(xs->dev->flags & IFF_UP))) + return -ENETDOWN; + if (unlikely(!xs->tx)) + return -ENOBUFS; + + return xs->zc ? xsk_zc_xmit(xs) : xsk_generic_xmit(sk); +} + static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len) { bool need_wait = !(m->msg_flags & MSG_DONTWAIT); @@ -402,21 +412,18 @@ static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len) if (unlikely(!xsk_is_bound(xs))) return -ENXIO; - if (unlikely(!(xs->dev->flags & IFF_UP))) - return -ENETDOWN; - if (unlikely(!xs->tx)) - return -ENOBUFS; - if (need_wait) + if (unlikely(need_wait)) return -EOPNOTSUPP; - return (xs->zc) ? xsk_zc_xmit(sk) : xsk_generic_xmit(sk, m, total_len); + return __xsk_sendmsg(sk); } static unsigned int xsk_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait) { unsigned int mask = datagram_poll(file, sock, wait); - struct xdp_sock *xs = xdp_sk(sock->sk); + struct sock *sk = sock->sk; + struct xdp_sock *xs = xdp_sk(sk); struct net_device *dev; struct xdp_umem *umem; @@ -426,9 +433,14 @@ static unsigned int xsk_poll(struct file *file, struct socket *sock, dev = xs->dev; umem = xs->umem; - if (umem->need_wakeup) - dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, - umem->need_wakeup); + if (umem->need_wakeup) { + if (dev->netdev_ops->ndo_xsk_wakeup) + dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, + umem->need_wakeup); + else + /* Poll needs to drive Tx also in copy mode */ + __xsk_sendmsg(sk); + } if (xs->rx && !xskq_empty_desc(xs->rx)) mask |= POLLIN | POLLRDNORM; diff --git a/patches/ANDROID-AVB-error-handler-to-invalidate-vbmeta-partition.patch b/patches/ANDROID-AVB-error-handler-to-invalidate-vbmeta-partition.patch deleted file mode 100644 index 70ae0a1c0d9bd1b65379beb00085d65cff224d3e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-AVB-error-handler-to-invalidate-vbmeta-partition.patch +++ /dev/null @@ -1,332 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Zeuthen -Date: Tue, 24 Jan 2017 13:17:01 -0500 -Subject: ANDROID: AVB error handler to invalidate vbmeta partition. - -If androidboot.vbmeta.invalidate_on_error is 'yes' and -androidboot.vbmeta.device is set and points to a device with vbmeta -magic, this header will be overwritten upon an irrecoverable dm-verity -error. The side-effect of this is that the slot will fail to verify on -next reboot, effectively triggering the boot loader to fallback to -another slot. This work both if the vbmeta struct is at the start of a -partition or if there's an AVB footer at the end. - -This code is based on drivers/md/dm-verity-chromeos.c from ChromiumOS. - -Bug: 31622239 -Bug: 120445368 -Test: Manually tested (other arch). -Signed-off-by: David Zeuthen -[astrachan: re-diffed against a kernel without dm-android-verity] -Change-Id: I571b5a75461da38ad832a9bea33c298bef859e26 -Signed-off-by: Alistair Strachan ---- - drivers/md/Kconfig | 11 ++ - drivers/md/Makefile | 4 + - drivers/md/dm-verity-avb.c | 229 ++++++++++++++++++++++++++++++++++ - drivers/md/dm-verity-target.c | 6 +- - drivers/md/dm-verity.h | 2 + - 5 files changed, 251 insertions(+), 1 deletion(-) - create mode 100644 drivers/md/dm-verity-avb.c - -diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig -index aa98953f4462..a744ba61ad21 100644 ---- a/drivers/md/Kconfig -+++ b/drivers/md/Kconfig -@@ -517,6 +517,17 @@ config DM_VERITY_VERIFY_ROOTHASH_SIG - - If unsure, say N. - -+config DM_VERITY_AVB -+ tristate "Support AVB specific verity error behavior" -+ depends on DM_VERITY -+ ---help--- -+ Enables Android Verified Boot platform-specific error -+ behavior. In particular, it will modify the vbmeta partition -+ specified on the kernel command-line when non-transient error -+ occurs (followed by a panic). -+ -+ If unsure, say N. -+ - config DM_VERITY_FEC - bool "Verity forward error correction support" - depends on DM_VERITY -diff --git a/drivers/md/Makefile b/drivers/md/Makefile -index d91a7edcd2ab..356b32d6b158 100644 ---- a/drivers/md/Makefile -+++ b/drivers/md/Makefile -@@ -80,6 +80,10 @@ ifeq ($(CONFIG_DM_UEVENT),y) - dm-mod-objs += dm-uevent.o - endif - -+ifeq ($(CONFIG_DM_VERITY_AVB),y) -+dm-verity-objs += dm-verity-avb.o -+endif -+ - ifeq ($(CONFIG_DM_VERITY_FEC),y) - dm-verity-objs += dm-verity-fec.o - endif -diff --git a/drivers/md/dm-verity-avb.c b/drivers/md/dm-verity-avb.c -new file mode 100644 -index 000000000000..a9f102aa379e ---- /dev/null -+++ b/drivers/md/dm-verity-avb.c -@@ -0,0 +1,229 @@ -+/* -+ * Copyright (C) 2017 Google. -+ * -+ * This file is released under the GPLv2. -+ * -+ * Based on drivers/md/dm-verity-chromeos.c -+ */ -+ -+#include -+#include -+#include -+ -+#define DM_MSG_PREFIX "verity-avb" -+ -+/* Set via module parameters. */ -+static char avb_vbmeta_device[64]; -+static char avb_invalidate_on_error[4]; -+ -+static void invalidate_vbmeta_endio(struct bio *bio) -+{ -+ if (bio->bi_status) -+ DMERR("invalidate_vbmeta_endio: error %d", bio->bi_status); -+ complete(bio->bi_private); -+} -+ -+static int invalidate_vbmeta_submit(struct bio *bio, -+ struct block_device *bdev, -+ int op, int access_last_sector, -+ struct page *page) -+{ -+ DECLARE_COMPLETION_ONSTACK(wait); -+ -+ bio->bi_private = &wait; -+ bio->bi_end_io = invalidate_vbmeta_endio; -+ bio_set_dev(bio, bdev); -+ bio_set_op_attrs(bio, op, REQ_SYNC); -+ -+ bio->bi_iter.bi_sector = 0; -+ if (access_last_sector) { -+ sector_t last_sector; -+ -+ last_sector = (i_size_read(bdev->bd_inode)>>SECTOR_SHIFT) - 1; -+ bio->bi_iter.bi_sector = last_sector; -+ } -+ if (!bio_add_page(bio, page, PAGE_SIZE, 0)) { -+ DMERR("invalidate_vbmeta_submit: bio_add_page error"); -+ return -EIO; -+ } -+ -+ submit_bio(bio); -+ /* Wait up to 2 seconds for completion or fail. */ -+ if (!wait_for_completion_timeout(&wait, msecs_to_jiffies(2000))) -+ return -EIO; -+ return 0; -+} -+ -+static int invalidate_vbmeta(dev_t vbmeta_devt) -+{ -+ int ret = 0; -+ struct block_device *bdev; -+ struct bio *bio; -+ struct page *page; -+ fmode_t dev_mode; -+ /* Ensure we do synchronous unblocked I/O. We may also need -+ * sync_bdev() on completion, but it really shouldn't. -+ */ -+ int access_last_sector = 0; -+ -+ DMINFO("invalidate_vbmeta: acting on device %d:%d", -+ MAJOR(vbmeta_devt), MINOR(vbmeta_devt)); -+ -+ /* First we open the device for reading. */ -+ dev_mode = FMODE_READ | FMODE_EXCL; -+ bdev = blkdev_get_by_dev(vbmeta_devt, dev_mode, -+ invalidate_vbmeta); -+ if (IS_ERR(bdev)) { -+ DMERR("invalidate_kernel: could not open device for reading"); -+ dev_mode = 0; -+ ret = -ENOENT; -+ goto failed_to_read; -+ } -+ -+ bio = bio_alloc(GFP_NOIO, 1); -+ if (!bio) { -+ ret = -ENOMEM; -+ goto failed_bio_alloc; -+ } -+ -+ page = alloc_page(GFP_NOIO); -+ if (!page) { -+ ret = -ENOMEM; -+ goto failed_to_alloc_page; -+ } -+ -+ access_last_sector = 0; -+ ret = invalidate_vbmeta_submit(bio, bdev, REQ_OP_READ, -+ access_last_sector, page); -+ if (ret) { -+ DMERR("invalidate_vbmeta: error reading"); -+ goto failed_to_submit_read; -+ } -+ -+ /* We have a page. Let's make sure it looks right. */ -+ if (memcmp("AVB0", page_address(page), 4) == 0) { -+ /* Stamp it. */ -+ memcpy(page_address(page), "AVE0", 4); -+ DMINFO("invalidate_vbmeta: found vbmeta partition"); -+ } else { -+ /* Could be this is on a AVB footer, check. Also, since the -+ * AVB footer is in the last 64 bytes, adjust for the fact that -+ * we're dealing with 512-byte sectors. -+ */ -+ size_t offset = (1<bi_remaining. -+ */ -+ bio_reset(bio); -+ -+ ret = invalidate_vbmeta_submit(bio, bdev, REQ_OP_WRITE, -+ access_last_sector, page); -+ if (ret) { -+ DMERR("invalidate_vbmeta: error writing"); -+ goto failed_to_submit_write; -+ } -+ -+ DMERR("invalidate_vbmeta: completed."); -+ ret = 0; -+failed_to_submit_write: -+failed_to_write: -+invalid_header: -+ __free_page(page); -+failed_to_submit_read: -+ /* Technically, we'll leak a page with the pending bio, but -+ * we're about to reboot anyway. -+ */ -+failed_to_alloc_page: -+ bio_put(bio); -+failed_bio_alloc: -+ if (dev_mode) -+ blkdev_put(bdev, dev_mode); -+failed_to_read: -+ return ret; -+} -+ -+void dm_verity_avb_error_handler(void) -+{ -+ dev_t dev; -+ -+ DMINFO("AVB error handler called for %s", avb_vbmeta_device); -+ -+ if (strcmp(avb_invalidate_on_error, "yes") != 0) { -+ DMINFO("Not configured to invalidate"); -+ return; -+ } -+ -+ if (avb_vbmeta_device[0] == '\0') { -+ DMERR("avb_vbmeta_device parameter not set"); -+ goto fail_no_dev; -+ } -+ -+ dev = name_to_dev_t(avb_vbmeta_device); -+ if (!dev) { -+ DMERR("No matching partition for device: %s", -+ avb_vbmeta_device); -+ goto fail_no_dev; -+ } -+ -+ invalidate_vbmeta(dev); -+ -+fail_no_dev: -+ ; -+} -+ -+static int __init dm_verity_avb_init(void) -+{ -+ DMINFO("AVB error handler initialized with vbmeta device: %s", -+ avb_vbmeta_device); -+ return 0; -+} -+ -+static void __exit dm_verity_avb_exit(void) -+{ -+} -+ -+module_init(dm_verity_avb_init); -+module_exit(dm_verity_avb_exit); -+ -+MODULE_AUTHOR("David Zeuthen "); -+MODULE_DESCRIPTION("AVB-specific error handler for dm-verity"); -+MODULE_LICENSE("GPL"); -+ -+/* Declare parameter with no module prefix */ -+#undef MODULE_PARAM_PREFIX -+#define MODULE_PARAM_PREFIX "androidboot.vbmeta." -+module_param_string(device, avb_vbmeta_device, sizeof(avb_vbmeta_device), 0); -+module_param_string(invalidate_on_error, avb_invalidate_on_error, -+ sizeof(avb_invalidate_on_error), 0); -diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c -index 4fb33e7562c5..99cee512273f 100644 ---- a/drivers/md/dm-verity-target.c -+++ b/drivers/md/dm-verity-target.c -@@ -251,8 +251,12 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type, - if (v->mode == DM_VERITY_MODE_LOGGING) - return 0; - -- if (v->mode == DM_VERITY_MODE_RESTART) -+ if (v->mode == DM_VERITY_MODE_RESTART) { -+#ifdef CONFIG_DM_VERITY_AVB -+ dm_verity_avb_error_handler(); -+#endif - kernel_restart("dm-verity device corrupted"); -+ } - - return 1; - } -diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h -index 641b9e3a399b..adbd64fde481 100644 ---- a/drivers/md/dm-verity.h -+++ b/drivers/md/dm-verity.h -@@ -128,4 +128,6 @@ extern int verity_hash(struct dm_verity *v, struct ahash_request *req, - extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io, - sector_t block, u8 *digest, bool *is_zero); - -+extern void dm_verity_avb_error_handler(void); -+ - #endif /* DM_VERITY_H */ diff --git a/patches/ANDROID-Add-an-IOCTL-to-check-ION-ABI-version.patch b/patches/ANDROID-Add-an-IOCTL-to-check-ION-ABI-version.patch deleted file mode 100644 index bbf4b8f97a65d30ad9fc33d541a3001be8cd2dcf..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Add-an-IOCTL-to-check-ION-ABI-version.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hridya Valsaraju -Date: Wed, 2 Oct 2019 14:32:19 -0700 -Subject: ANDROID: Add an IOCTL to check ION ABI version - -Userspace needs a way to detect ION ABI version at runtime to determine -heap IDs. CURRENT_ION_ABI_VERSION is set to 2 considering legacy and -upstream versions as 0 and 1. - -Bug: 140916230 -Test: make - -Signed-off-by: Hridya Valsaraju - -Change-Id: Ie9d9e23c2d8323620832906d33745d599cbce6be ---- - drivers/staging/android/ion/ion.c | 6 ++++++ - include/uapi/linux/ion.h | 7 +++++++ - 2 files changed, 13 insertions(+) - -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index 2c915579f60b..a499a76453ee 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -27,6 +27,8 @@ - - #include "ion_private.h" - -+#define ION_CURRENT_ABI_VERSION 2 -+ - static struct ion_device *internal_dev; - - /* Entry into ION allocator for rest of the kernel */ -@@ -108,6 +110,7 @@ static int ion_query_heaps(struct ion_heap_query *query) - union ion_ioctl_arg { - struct ion_allocation_data allocation; - struct ion_heap_query query; -+ u32 ion_abi_version; - }; - - static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) -@@ -169,6 +172,9 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - case ION_IOC_HEAP_QUERY: - ret = ion_query_heaps(&data.query); - break; -+ case ION_IOC_ABI_VERSION: -+ data.ion_abi_version = ION_CURRENT_ABI_VERSION; -+ break; - default: - return -ENOTTY; - } -diff --git a/include/uapi/linux/ion.h b/include/uapi/linux/ion.h -index ad773e5fa4d2..fdb2eba7f500 100644 ---- a/include/uapi/linux/ion.h -+++ b/include/uapi/linux/ion.h -@@ -159,4 +159,11 @@ struct ion_heap_query { - #define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, \ - struct ion_heap_query) - -+/** -+ * DOC: ION_IOC_HEAP_ABI_VERSION - return ABI version -+ * -+ * Returns ABI version for this driver -+ */ -+#define ION_IOC_ABI_VERSION _IOR(ION_IOC_MAGIC, 9, \ -+ __u32) - #endif /* _UAPI_LINUX_ION_H */ diff --git a/patches/ANDROID-Add-initial-rockpi4_defconfig.patch b/patches/ANDROID-Add-initial-rockpi4_defconfig.patch deleted file mode 100644 index 9dd50e8ff11fb604a7a0c862d8ca7545758664f5..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Add-initial-rockpi4_defconfig.patch +++ /dev/null @@ -1,561 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tristan Muntsinger -Date: Thu, 25 Jul 2019 13:48:04 -0700 -Subject: ANDROID: Add initial rockpi4_defconfig - -This is for the Rock Pi 4B board from Radxa with Rockchip's RK3399. - -Bug: 118442619 -Change-Id: If2ba4198ef268e5b249e909b1987d52f1c8d0def -Signed-off-by: Tristan Muntsinger ---- - arch/arm64/configs/rockpi4_defconfig | 540 +++++++++++++++++++++++++++ - 1 file changed, 540 insertions(+) - create mode 100644 arch/arm64/configs/rockpi4_defconfig - -diff --git a/arch/arm64/configs/rockpi4_defconfig b/arch/arm64/configs/rockpi4_defconfig -new file mode 100644 -index 000000000000..6d0cf70f3757 ---- /dev/null -+++ b/arch/arm64/configs/rockpi4_defconfig -@@ -0,0 +1,540 @@ -+CONFIG_AUDIT=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_PREEMPT=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_PSI=y -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_MEMCG=y -+CONFIG_MEMCG_SWAP=y -+CONFIG_BLK_CGROUP=y -+CONFIG_RT_GROUP_SCHED=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_CGROUP_BPF=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_RD_BZIP2 is not set -+# CONFIG_RD_LZMA is not set -+# CONFIG_RD_XZ is not set -+# CONFIG_RD_LZO is not set -+# CONFIG_RD_LZ4 is not set -+# CONFIG_SYSFS_SYSCALL is not set -+CONFIG_FHANDLE=y -+CONFIG_KALLSYMS_ALL=y -+CONFIG_BPF_SYSCALL=y -+# CONFIG_RSEQ is not set -+CONFIG_EMBEDDED=y -+# CONFIG_VM_EVENT_COUNTERS is not set -+# CONFIG_COMPAT_BRK is not set -+# CONFIG_SLAB_MERGE_DEFAULT is not set -+CONFIG_SLAB_FREELIST_RANDOM=y -+CONFIG_SLAB_FREELIST_HARDENED=y -+CONFIG_PROFILING=y -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_SCHED_MC=y -+CONFIG_SECCOMP=y -+CONFIG_PARAVIRT=y -+CONFIG_COMPAT=y -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y -+CONFIG_RANDOMIZE_BASE=y -+CONFIG_CMDLINE="" -+# CONFIG_CMDLINE_FORCE is not set -+# CONFIG_EFI is not set -+CONFIG_PM_WAKELOCKS=y -+CONFIG_PM_WAKELOCKS_LIMIT=0 -+# CONFIG_PM_WAKELOCKS_GC is not set -+CONFIG_ENERGY_MODEL=y -+CONFIG_CPU_IDLE=y -+CONFIG_ARM_CPUIDLE=y -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_TIMES=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_ARM_SCPI_CPUFREQ=y -+CONFIG_ARM_SCMI_CPUFREQ=y -+CONFIG_ARM_SCMI_PROTOCOL=y -+# CONFIG_ARM_SCMI_POWER_DOMAIN is not set -+CONFIG_ARM_SCPI_PROTOCOL=y -+# CONFIG_ARM_SCPI_POWER_DOMAIN is not set -+CONFIG_VIRTUALIZATION=y -+CONFIG_KVM=y -+CONFIG_VHOST_VSOCK=y -+CONFIG_ARM64_CRYPTO=y -+CONFIG_CRYPTO_AES_ARM64=y -+CONFIG_KPROBES=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -+CONFIG_BINFMT_MISC=y -+# CONFIG_SPARSEMEM_VMEMMAP is not set -+CONFIG_MEMORY_HOTPLUG=y -+CONFIG_TRANSPARENT_HUGEPAGE=y -+CONFIG_CMA=y -+CONFIG_CMA_AREAS=16 -+CONFIG_ZSMALLOC=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_XFRM_INTERFACE=y -+CONFIG_XFRM_STATISTICS=y -+CONFIG_NET_KEY=y -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_PNP=y -+CONFIG_NET_IPGRE_DEMUX=y -+CONFIG_NET_IPVTI=y -+CONFIG_INET_ESP=y -+CONFIG_INET_UDP_DIAG=y -+CONFIG_INET_DIAG_DESTROY=y -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_IPV6_ROUTE_INFO=y -+CONFIG_IPV6_OPTIMISTIC_DAD=y -+CONFIG_INET6_ESP=y -+CONFIG_INET6_IPCOMP=y -+CONFIG_IPV6_MIP6=y -+CONFIG_IPV6_VTI=y -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=y -+CONFIG_NF_CONNTRACK_SECMARK=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_AMANDA=y -+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_CT=y -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -+CONFIG_NETFILTER_XT_TARGET_MARK=y -+CONFIG_NETFILTER_XT_TARGET_NFLOG=y -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -+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 -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -+CONFIG_NETFILTER_XT_MATCH_HELPER=y -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -+CONFIG_NETFILTER_XT_MATCH_LENGTH=y -+CONFIG_NETFILTER_XT_MATCH_LIMIT=y -+CONFIG_NETFILTER_XT_MATCH_MAC=y -+CONFIG_NETFILTER_XT_MATCH_MARK=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 -+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -+CONFIG_NETFILTER_XT_MATCH_SOCKET=y -+CONFIG_NETFILTER_XT_MATCH_STATE=y -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -+CONFIG_NETFILTER_XT_MATCH_STRING=y -+CONFIG_NETFILTER_XT_MATCH_TIME=y -+CONFIG_NETFILTER_XT_MATCH_U32=y -+CONFIG_IP_NF_IPTABLES=y -+CONFIG_IP_NF_MATCH_ECN=y -+CONFIG_IP_NF_MATCH_TTL=y -+CONFIG_IP_NF_FILTER=y -+CONFIG_IP_NF_TARGET_REJECT=y -+CONFIG_IP_NF_NAT=y -+CONFIG_IP_NF_TARGET_MASQUERADE=y -+CONFIG_IP_NF_TARGET_NETMAP=y -+CONFIG_IP_NF_TARGET_REDIRECT=y -+CONFIG_IP_NF_MANGLE=y -+CONFIG_IP_NF_RAW=y -+CONFIG_IP_NF_SECURITY=y -+CONFIG_IP_NF_ARPTABLES=y -+CONFIG_IP_NF_ARPFILTER=y -+CONFIG_IP_NF_ARP_MANGLE=y -+CONFIG_IP6_NF_IPTABLES=y -+CONFIG_IP6_NF_MATCH_RPFILTER=y -+CONFIG_IP6_NF_FILTER=y -+CONFIG_IP6_NF_TARGET_REJECT=y -+CONFIG_IP6_NF_MANGLE=y -+CONFIG_IP6_NF_RAW=y -+CONFIG_L2TP=y -+CONFIG_BRIDGE=y -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_HTB=y -+CONFIG_NET_SCH_INGRESS=y -+CONFIG_NET_CLS_U32=y -+CONFIG_NET_CLS_BPF=y -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_U32=y -+CONFIG_NET_CLS_ACT=y -+CONFIG_VSOCKETS=y -+CONFIG_VIRTIO_VSOCKETS=y -+CONFIG_BT=y -+CONFIG_CFG80211=y -+# CONFIG_CFG80211_DEFAULT_PS is not set -+# CONFIG_CFG80211_CRDA_SUPPORT is not set -+CONFIG_MAC80211=y -+# CONFIG_MAC80211_RC_MINSTREL is not set -+CONFIG_RFKILL=y -+CONFIG_PCI=y -+CONFIG_PCI_HOST_GENERIC=y -+CONFIG_DEVTMPFS=y -+# CONFIG_ALLOW_DEV_COREDUMP is not set -+CONFIG_DEBUG_DEVRES=y -+CONFIG_ZRAM=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=8192 -+CONFIG_VIRTIO_BLK=y -+CONFIG_UID_SYS_STATS=y -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_UFSHCD=y -+CONFIG_SCSI_UFSHCD_PLATFORM=y -+CONFIG_MD=y -+CONFIG_BLK_DEV_DM=y -+CONFIG_DM_CRYPT=y -+CONFIG_DM_UEVENT=y -+CONFIG_DM_VERITY=y -+CONFIG_DM_VERITY_AVB=y -+CONFIG_DM_VERITY_FEC=y -+CONFIG_DM_BOW=y -+CONFIG_NETDEVICES=y -+CONFIG_TUN=y -+CONFIG_VIRTIO_NET=y -+# CONFIG_NET_VENDOR_3COM is not set -+# CONFIG_NET_VENDOR_ADAPTEC is not set -+# CONFIG_NET_VENDOR_AGERE is not set -+# CONFIG_NET_VENDOR_ALACRITECH is not set -+# CONFIG_NET_VENDOR_ALTEON is not set -+# CONFIG_NET_VENDOR_AMAZON is not set -+# CONFIG_NET_VENDOR_AMD is not set -+# CONFIG_NET_VENDOR_AQUANTIA is not set -+# CONFIG_NET_VENDOR_ARC is not set -+# CONFIG_NET_VENDOR_ATHEROS is not set -+# CONFIG_NET_VENDOR_AURORA is not set -+# CONFIG_NET_VENDOR_BROADCOM is not set -+# CONFIG_NET_VENDOR_BROCADE is not set -+# CONFIG_NET_VENDOR_CADENCE is not set -+# CONFIG_NET_VENDOR_CAVIUM is not set -+# CONFIG_NET_VENDOR_CHELSIO is not set -+# CONFIG_NET_VENDOR_CISCO is not set -+# CONFIG_NET_VENDOR_CORTINA is not set -+# CONFIG_NET_VENDOR_DEC is not set -+# CONFIG_NET_VENDOR_DLINK is not set -+# CONFIG_NET_VENDOR_EMULEX is not set -+# CONFIG_NET_VENDOR_EZCHIP is not set -+# CONFIG_NET_VENDOR_HISILICON is not set -+# CONFIG_NET_VENDOR_HP is not set -+# CONFIG_NET_VENDOR_HUAWEI is not set -+# CONFIG_NET_VENDOR_INTEL is not set -+# CONFIG_NET_VENDOR_MARVELL is not set -+# CONFIG_NET_VENDOR_MELLANOX is not set -+# CONFIG_NET_VENDOR_MICREL is not set -+# CONFIG_NET_VENDOR_MICROCHIP is not set -+# CONFIG_NET_VENDOR_MICROSEMI is not set -+# CONFIG_NET_VENDOR_MYRI is not set -+# CONFIG_NET_VENDOR_NATSEMI is not set -+# CONFIG_NET_VENDOR_NETERION is not set -+# CONFIG_NET_VENDOR_NETRONOME is not set -+# CONFIG_NET_VENDOR_NI is not set -+# CONFIG_NET_VENDOR_NVIDIA is not set -+# CONFIG_NET_VENDOR_OKI is not set -+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set -+# CONFIG_NET_VENDOR_QLOGIC is not set -+# CONFIG_NET_VENDOR_QUALCOMM is not set -+# CONFIG_NET_VENDOR_RDC is not set -+# CONFIG_NET_VENDOR_REALTEK is not set -+# CONFIG_NET_VENDOR_RENESAS is not set -+# CONFIG_NET_VENDOR_ROCKER is not set -+# CONFIG_NET_VENDOR_SAMSUNG is not set -+# CONFIG_NET_VENDOR_SEEQ is not set -+# CONFIG_NET_VENDOR_SOLARFLARE is not set -+# CONFIG_NET_VENDOR_SILAN is not set -+# CONFIG_NET_VENDOR_SIS is not set -+# CONFIG_NET_VENDOR_SMSC is not set -+# CONFIG_NET_VENDOR_SOCIONEXT is not set -+CONFIG_STMMAC_ETH=y -+# CONFIG_DWMAC_GENERIC is not set -+# CONFIG_NET_VENDOR_SUN is not set -+# CONFIG_NET_VENDOR_SYNOPSYS is not set -+# CONFIG_NET_VENDOR_TEHUTI is not set -+# CONFIG_NET_VENDOR_TI is not set -+# CONFIG_NET_VENDOR_VIA is not set -+# CONFIG_NET_VENDOR_WIZNET is not set -+CONFIG_ROCKCHIP_PHY=y -+CONFIG_PPP=y -+CONFIG_PPP_BSDCOMP=y -+CONFIG_PPP_DEFLATE=y -+CONFIG_PPP_MPPE=y -+CONFIG_PPTP=y -+CONFIG_PPPOL2TP=y -+CONFIG_USB_RTL8152=y -+CONFIG_USB_USBNET=y -+# CONFIG_USB_NET_AX8817X is not set -+# CONFIG_USB_NET_AX88179_178A is not set -+# CONFIG_USB_NET_CDCETHER is not set -+# CONFIG_USB_NET_CDC_NCM is not set -+# CONFIG_USB_NET_NET1080 is not set -+# CONFIG_USB_NET_CDC_SUBSET is not set -+# CONFIG_USB_NET_ZAURUS is not set -+# CONFIG_WLAN_VENDOR_ADMTEK is not set -+# CONFIG_WLAN_VENDOR_ATH is not set -+# CONFIG_WLAN_VENDOR_ATMEL is not set -+# CONFIG_WLAN_VENDOR_BROADCOM is not set -+# CONFIG_WLAN_VENDOR_CISCO is not set -+# CONFIG_WLAN_VENDOR_INTEL is not set -+# CONFIG_WLAN_VENDOR_INTERSIL is not set -+# CONFIG_WLAN_VENDOR_MARVELL is not set -+# CONFIG_WLAN_VENDOR_MEDIATEK is not set -+# CONFIG_WLAN_VENDOR_RALINK is not set -+# CONFIG_WLAN_VENDOR_REALTEK is not set -+# CONFIG_WLAN_VENDOR_RSI is not set -+# CONFIG_WLAN_VENDOR_ST is not set -+# CONFIG_WLAN_VENDOR_TI is not set -+# CONFIG_WLAN_VENDOR_ZYDAS is not set -+# CONFIG_WLAN_VENDOR_QUANTENNA is not set -+CONFIG_VIRT_WIFI=y -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_UINPUT=y -+# CONFIG_VT is not set -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_EXAR is not set -+CONFIG_SERIAL_8250_NR_UARTS=48 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_MANY_PORTS=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_8250_DW=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_VIRTIO_CONSOLE=y -+CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_VIRTIO=y -+# CONFIG_HW_RANDOM_CAVIUM is not set -+# CONFIG_DEVPORT is not set -+# CONFIG_I2C_COMPAT is not set -+CONFIG_I2C_MUX_PINCTRL=y -+CONFIG_I2C_DEMUX_PINCTRL=y -+# CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_I2C_DESIGNWARE_PLATFORM=y -+CONFIG_I2C_DESIGNWARE_SLAVE=y -+CONFIG_I2C_RK3X=y -+CONFIG_SPI=y -+CONFIG_SPI_ROCKCHIP=y -+CONFIG_SPMI=y -+CONFIG_DEBUG_PINCTRL=y -+CONFIG_PINCTRL_AMD=y -+CONFIG_PINCTRL_SINGLE=y -+CONFIG_PINCTRL_RK805=y -+CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_GENERIC_PLATFORM=y -+CONFIG_POWER_AVS=y -+CONFIG_ROCKCHIP_IODOMAIN=y -+CONFIG_POWER_RESET_GPIO=y -+CONFIG_POWER_RESET_GPIO_RESTART=y -+CONFIG_POWER_RESET_RESTART=y -+CONFIG_POWER_RESET_SYSCON=y -+CONFIG_POWER_RESET_SYSCON_POWEROFF=y -+CONFIG_SYSCON_REBOOT_MODE=y -+# CONFIG_HWMON is not set -+CONFIG_THERMAL=y -+CONFIG_THERMAL_GOV_USER_SPACE=y -+CONFIG_CPU_THERMAL=y -+CONFIG_DEVFREQ_THERMAL=y -+CONFIG_ROCKCHIP_THERMAL=y -+CONFIG_WATCHDOG=y -+CONFIG_WATCHDOG_PRETIMEOUT_GOV=y -+# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set -+CONFIG_DW_WATCHDOG=y -+CONFIG_MFD_ACT8945A=y -+CONFIG_MFD_RK808=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_DEBUG=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=y -+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y -+CONFIG_REGULATOR_USERSPACE_CONSUMER=y -+CONFIG_REGULATOR_GPIO=y -+CONFIG_REGULATOR_PWM=y -+CONFIG_REGULATOR_RK808=y -+CONFIG_REGULATOR_VCTRL=y -+CONFIG_MEDIA_SUPPORT=y -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_VIDEO_V4L2_SUBDEV_API=y -+# CONFIG_VGA_ARB is not set -+CONFIG_DRM=y -+# CONFIG_DRM_FBDEV_EMULATION is not set -+CONFIG_DRM_ROCKCHIP=y -+CONFIG_ROCKCHIP_DW_HDMI=y -+CONFIG_DRM_VIRTIO_GPU=y -+# CONFIG_LCD_CLASS_DEVICE is not set -+CONFIG_BACKLIGHT_CLASS_DEVICE=y -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_HRTIMER=y -+CONFIG_SND_DYNAMIC_MINORS=y -+# CONFIG_SND_SUPPORT_OLD_API is not set -+# CONFIG_SND_VERBOSE_PROCFS is not set -+# CONFIG_SND_DRIVERS is not set -+CONFIG_SND_INTEL8X0=y -+CONFIG_SND_USB_AUDIO=y -+CONFIG_SND_SOC=y -+CONFIG_SND_SOC_TS3A227E=y -+CONFIG_HIDRAW=y -+CONFIG_UHID=y -+CONFIG_HID_APPLE=y -+CONFIG_HID_ELECOM=y -+CONFIG_HID_MAGICMOUSE=y -+CONFIG_HID_MICROSOFT=y -+CONFIG_HID_MULTITOUCH=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_OTG=y -+CONFIG_USB_OTG_FSM=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_ROOT_HUB_TT=y -+CONFIG_USB_EHCI_HCD_PLATFORM=y -+CONFIG_USB_OHCI_HCD=y -+# CONFIG_USB_OHCI_HCD_PCI is not set -+CONFIG_USB_OHCI_HCD_PLATFORM=y -+CONFIG_USB_GADGET=y -+CONFIG_USB_CONFIGFS=y -+CONFIG_USB_CONFIGFS_UEVENT=y -+CONFIG_USB_CONFIGFS_F_FS=y -+CONFIG_USB_CONFIGFS_F_ACC=y -+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y -+CONFIG_USB_CONFIGFS_F_MIDI=y -+CONFIG_MMC=y -+# CONFIG_PWRSEQ_EMMC is not set -+# CONFIG_PWRSEQ_SIMPLE is not set -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI_OF_ARASAN=y -+CONFIG_MMC_SDHCI_OF_DWCMSHC=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_MMC_CQHCI=y -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_SYSTOHC is not set -+CONFIG_RTC_DRV_RK808=y -+CONFIG_RTC_DRV_PL030=y -+CONFIG_RTC_DRV_PL031=y -+CONFIG_DMADEVICES=y -+CONFIG_PL330_DMA=y -+CONFIG_VIRTIO_PCI=y -+# CONFIG_VIRTIO_PCI_LEGACY is not set -+CONFIG_VIRTIO_INPUT=y -+CONFIG_VIRTIO_MMIO=y -+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y -+CONFIG_STAGING=y -+CONFIG_ASHMEM=y -+CONFIG_ANDROID_VSOC=y -+CONFIG_ION=y -+CONFIG_COMMON_CLK_RK808=y -+CONFIG_COMMON_CLK_SCPI=y -+# CONFIG_COMMON_CLK_XGENE is not set -+CONFIG_HWSPINLOCK=y -+# CONFIG_FSL_ERRATUM_A008585 is not set -+# CONFIG_HISILICON_ERRATUM_161010101 is not set -+CONFIG_MAILBOX=y -+CONFIG_ROCKCHIP_MBOX=y -+CONFIG_ROCKCHIP_IOMMU=y -+CONFIG_ARM_SMMU=y -+CONFIG_ROCKCHIP_PM_DOMAINS=y -+CONFIG_DEVFREQ_GOV_PERFORMANCE=y -+CONFIG_DEVFREQ_GOV_POWERSAVE=y -+CONFIG_DEVFREQ_GOV_USERSPACE=y -+CONFIG_DEVFREQ_GOV_PASSIVE=y -+CONFIG_ARM_RK3399_DMC_DEVFREQ=y -+CONFIG_PWM=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_PHY_ROCKCHIP_EMMC=y -+CONFIG_PHY_ROCKCHIP_INNO_HDMI=y -+CONFIG_PHY_ROCKCHIP_INNO_USB2=y -+CONFIG_PHY_ROCKCHIP_USB=y -+CONFIG_ANDROID=y -+CONFIG_ANDROID_BINDER_IPC=y -+CONFIG_ROCKCHIP_EFUSE=y -+CONFIG_INTERCONNECT=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_F2FS_FS=y -+CONFIG_F2FS_FS_SECURITY=y -+CONFIG_FS_ENCRYPTION=y -+# CONFIG_DNOTIFY is not set -+CONFIG_QUOTA=y -+CONFIG_QFMT_V2=y -+CONFIG_FUSE_FS=y -+CONFIG_OVERLAY_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=y -+CONFIG_PSTORE=y -+CONFIG_PSTORE_CONSOLE=y -+CONFIG_PSTORE_RAM=y -+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y -+CONFIG_SECURITY=y -+CONFIG_SECURITY_NETWORK=y -+CONFIG_HARDENED_USERCOPY=y -+CONFIG_SECURITY_SELINUX=y -+CONFIG_CRYPTO_ADIANTUM=y -+CONFIG_CRYPTO_MD4=y -+CONFIG_CRYPTO_SHA512=y -+CONFIG_CRYPTO_LZ4=y -+CONFIG_CRYPTO_ZSTD=y -+CONFIG_CRYPTO_ANSI_CPRNG=y -+CONFIG_CRYPTO_DEV_ROCKCHIP=y -+CONFIG_CRYPTO_DEV_VIRTIO=y -+CONFIG_CRC_CCITT=y -+CONFIG_CRC8=y -+CONFIG_XZ_DEC=y -+CONFIG_DMA_CMA=y -+CONFIG_PRINTK_TIME=y -+CONFIG_DEBUG_INFO=y -+# CONFIG_ENABLE_MUST_CHECK is not set -+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -+CONFIG_MAGIC_SYSRQ=y -+CONFIG_DEBUG_STACK_USAGE=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_SOFTLOCKUP_DETECTOR=y -+# CONFIG_DETECT_HUNG_TASK is not set -+CONFIG_PANIC_TIMEOUT=5 -+CONFIG_SCHEDSTATS=y -+CONFIG_FUNCTION_TRACER=y -+# CONFIG_RUNTIME_TESTING_MENU is not set -+CONFIG_CORESIGHT=y -+CONFIG_CORESIGHT_STM=y diff --git a/patches/ANDROID-Add-initial-x86_64-gki_defconfig.patch b/patches/ANDROID-Add-initial-x86_64-gki_defconfig.patch deleted file mode 100644 index 6e59028e8c336e27700885ca12c6f193a217a5b5..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Add-initial-x86_64-gki_defconfig.patch +++ /dev/null @@ -1,382 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Fri, 17 May 2019 16:52:29 -0700 -Subject: ANDROID: Add initial x86_64 gki_defconfig - -That is a copy from the aarch64 gki_defconfig. - -To be able to build in this configuration, - - + CONFIG_UNWINDER_FRAME_POINTER=y - -was necessary. - -Bug: 132113225 -Bug: 132629930 -Change-Id: I685ccea29efc7ba14f7b0a24f41983e37203f9a2 -Signed-off-by: Ram Muthiah -Signed-off-by: Matthias Maennich ---- - arch/x86/configs/gki_defconfig | 328 +++++++++++++++++++++++++++++++++ - build.config.gki.x86_64 | 17 ++ - 2 files changed, 345 insertions(+) - create mode 100644 arch/x86/configs/gki_defconfig - create mode 100644 build.config.gki.x86_64 - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -new file mode 100644 -index 000000000000..18ba312d0a60 ---- /dev/null -+++ b/arch/x86/configs/gki_defconfig -@@ -0,0 +1,328 @@ -+CONFIG_AUDIT=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_PREEMPT=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_PSI=y -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_MEMCG=y -+CONFIG_MEMCG_SWAP=y -+CONFIG_RT_GROUP_SCHED=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_CGROUP_BPF=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_RD_BZIP2 is not set -+# CONFIG_RD_LZMA is not set -+# CONFIG_RD_XZ is not set -+# CONFIG_RD_LZO is not set -+# CONFIG_RD_LZ4 is not set -+# CONFIG_SYSFS_SYSCALL is not set -+# CONFIG_FHANDLE is not set -+CONFIG_KALLSYMS_ALL=y -+CONFIG_BPF_SYSCALL=y -+# CONFIG_RSEQ is not set -+CONFIG_EMBEDDED=y -+# CONFIG_VM_EVENT_COUNTERS is not set -+# CONFIG_COMPAT_BRK is not set -+# CONFIG_SLAB_MERGE_DEFAULT is not set -+CONFIG_PROFILING=y -+CONFIG_PM_WAKELOCKS=y -+CONFIG_PM_WAKELOCKS_LIMIT=0 -+# CONFIG_PM_WAKELOCKS_GC is not set -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_TIMES=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_KPROBES=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -+# CONFIG_SPARSEMEM_VMEMMAP is not set -+CONFIG_TRANSPARENT_HUGEPAGE=y -+CONFIG_ZSMALLOC=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_XFRM_INTERFACE=y -+CONFIG_XFRM_STATISTICS=y -+CONFIG_NET_KEY=y -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_NET_IPGRE_DEMUX=y -+CONFIG_NET_IPVTI=y -+CONFIG_INET_ESP=y -+CONFIG_INET_UDP_DIAG=y -+CONFIG_INET_DIAG_DESTROY=y -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_IPV6_ROUTE_INFO=y -+CONFIG_IPV6_OPTIMISTIC_DAD=y -+CONFIG_INET6_ESP=y -+CONFIG_INET6_IPCOMP=y -+CONFIG_IPV6_MIP6=y -+CONFIG_IPV6_VTI=y -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=y -+CONFIG_NF_CONNTRACK_SECMARK=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_AMANDA=y -+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_CT=y -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -+CONFIG_NETFILTER_XT_TARGET_MARK=y -+CONFIG_NETFILTER_XT_TARGET_NFLOG=y -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -+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 -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -+CONFIG_NETFILTER_XT_MATCH_HELPER=y -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -+CONFIG_NETFILTER_XT_MATCH_LENGTH=y -+CONFIG_NETFILTER_XT_MATCH_LIMIT=y -+CONFIG_NETFILTER_XT_MATCH_MAC=y -+CONFIG_NETFILTER_XT_MATCH_MARK=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 -+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -+CONFIG_NETFILTER_XT_MATCH_SOCKET=y -+CONFIG_NETFILTER_XT_MATCH_STATE=y -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -+CONFIG_NETFILTER_XT_MATCH_STRING=y -+CONFIG_NETFILTER_XT_MATCH_TIME=y -+CONFIG_NETFILTER_XT_MATCH_U32=y -+CONFIG_IP_NF_IPTABLES=y -+CONFIG_IP_NF_MATCH_ECN=y -+CONFIG_IP_NF_MATCH_TTL=y -+CONFIG_IP_NF_FILTER=y -+CONFIG_IP_NF_TARGET_REJECT=y -+CONFIG_IP_NF_NAT=y -+CONFIG_IP_NF_TARGET_MASQUERADE=y -+CONFIG_IP_NF_TARGET_NETMAP=y -+CONFIG_IP_NF_TARGET_REDIRECT=y -+CONFIG_IP_NF_MANGLE=y -+CONFIG_IP_NF_RAW=y -+CONFIG_IP_NF_SECURITY=y -+CONFIG_IP_NF_ARPTABLES=y -+CONFIG_IP_NF_ARPFILTER=y -+CONFIG_IP_NF_ARP_MANGLE=y -+CONFIG_IP6_NF_IPTABLES=y -+CONFIG_IP6_NF_MATCH_RPFILTER=y -+CONFIG_IP6_NF_FILTER=y -+CONFIG_IP6_NF_TARGET_REJECT=y -+CONFIG_IP6_NF_MANGLE=y -+CONFIG_IP6_NF_RAW=y -+CONFIG_L2TP=y -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_HTB=y -+CONFIG_NET_SCH_INGRESS=y -+CONFIG_NET_CLS_U32=y -+CONFIG_NET_CLS_BPF=y -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_U32=y -+CONFIG_NET_CLS_ACT=y -+CONFIG_VSOCKETS=y -+CONFIG_VIRTIO_VSOCKETS=y -+CONFIG_CFG80211=y -+# CONFIG_CFG80211_DEFAULT_PS is not set -+# CONFIG_CFG80211_CRDA_SUPPORT is not set -+CONFIG_MAC80211=y -+# CONFIG_MAC80211_RC_MINSTREL is not set -+CONFIG_RFKILL=y -+# CONFIG_ALLOW_DEV_COREDUMP is not set -+CONFIG_DEBUG_DEVRES=y -+CONFIG_ZRAM=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=8192 -+CONFIG_VIRTIO_BLK=y -+CONFIG_UID_SYS_STATS=y -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_VIRTIO=y -+CONFIG_MD=y -+CONFIG_BLK_DEV_DM=y -+CONFIG_DM_CRYPT=y -+CONFIG_DM_UEVENT=y -+CONFIG_DM_VERITY=y -+CONFIG_DM_VERITY_AVB=y -+CONFIG_DM_VERITY_FEC=y -+CONFIG_DM_BOW=y -+CONFIG_NETDEVICES=y -+CONFIG_TUN=y -+CONFIG_VIRTIO_NET=y -+# CONFIG_ETHERNET is not set -+CONFIG_PHYLIB=y -+CONFIG_PPP=y -+CONFIG_PPP_BSDCOMP=y -+CONFIG_PPP_DEFLATE=y -+CONFIG_PPP_MPPE=y -+CONFIG_PPTP=y -+CONFIG_PPPOL2TP=y -+CONFIG_USB_RTL8152=y -+CONFIG_USB_USBNET=y -+# CONFIG_USB_NET_AX8817X is not set -+# CONFIG_USB_NET_AX88179_178A is not set -+# CONFIG_USB_NET_CDCETHER is not set -+# CONFIG_USB_NET_CDC_NCM is not set -+# CONFIG_USB_NET_NET1080 is not set -+# CONFIG_USB_NET_CDC_SUBSET is not set -+# CONFIG_USB_NET_ZAURUS is not set -+# CONFIG_WLAN_VENDOR_ADMTEK is not set -+# CONFIG_WLAN_VENDOR_ATH is not set -+# CONFIG_WLAN_VENDOR_ATMEL is not set -+# CONFIG_WLAN_VENDOR_BROADCOM is not set -+# CONFIG_WLAN_VENDOR_CISCO is not set -+# CONFIG_WLAN_VENDOR_INTEL is not set -+# CONFIG_WLAN_VENDOR_INTERSIL is not set -+# CONFIG_WLAN_VENDOR_MARVELL is not set -+# CONFIG_WLAN_VENDOR_MEDIATEK is not set -+# CONFIG_WLAN_VENDOR_RALINK is not set -+# CONFIG_WLAN_VENDOR_REALTEK is not set -+# CONFIG_WLAN_VENDOR_RSI is not set -+# CONFIG_WLAN_VENDOR_ST is not set -+# CONFIG_WLAN_VENDOR_TI is not set -+# CONFIG_WLAN_VENDOR_ZYDAS is not set -+# CONFIG_WLAN_VENDOR_QUANTENNA is not set -+CONFIG_VIRT_WIFI=y -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_UINPUT=y -+# CONFIG_VT is not set -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+CONFIG_SERIAL_8250_NR_UARTS=48 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_MANY_PORTS=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_VIRTIO_CONSOLE=y -+CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_VIRTIO=y -+# CONFIG_I2C_COMPAT is not set -+# CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_GPIOLIB=y -+# CONFIG_HWMON is not set -+CONFIG_DEVFREQ_THERMAL=y -+CONFIG_MEDIA_SUPPORT=y -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_DRM=y -+# CONFIG_DRM_FBDEV_EMULATION is not set -+CONFIG_DRM_VIRTIO_GPU=y -+CONFIG_BACKLIGHT_CLASS_DEVICE=y -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_HRTIMER=y -+CONFIG_SND_DYNAMIC_MINORS=y -+# CONFIG_SND_SUPPORT_OLD_API is not set -+# CONFIG_SND_VERBOSE_PROCFS is not set -+# CONFIG_SND_DRIVERS is not set -+# CONFIG_SND_USB is not set -+CONFIG_HIDRAW=y -+CONFIG_UHID=y -+CONFIG_HID_APPLE=y -+CONFIG_HID_ELECOM=y -+CONFIG_HID_MAGICMOUSE=y -+CONFIG_HID_MICROSOFT=y -+CONFIG_HID_MULTITOUCH=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB=y -+CONFIG_USB_GADGET=y -+CONFIG_USB_CONFIGFS=y -+CONFIG_USB_CONFIGFS_UEVENT=y -+CONFIG_USB_CONFIGFS_F_FS=y -+CONFIG_USB_CONFIGFS_F_ACC=y -+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y -+CONFIG_USB_CONFIGFS_F_MIDI=y -+CONFIG_MMC=y -+# CONFIG_MMC_BLOCK is not set -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_SYSTOHC is not set -+CONFIG_VIRTIO_BALLOON=y -+CONFIG_VIRTIO_INPUT=y -+CONFIG_VIRTIO_MMIO=y -+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y -+CONFIG_STAGING=y -+CONFIG_ASHMEM=y -+CONFIG_ION=y -+CONFIG_MAILBOX=y -+CONFIG_PM_DEVFREQ=y -+CONFIG_ANDROID=y -+CONFIG_ANDROID_BINDER_IPC=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_F2FS_FS=y -+CONFIG_F2FS_FS_SECURITY=y -+# CONFIG_DNOTIFY is not set -+CONFIG_QUOTA=y -+CONFIG_QFMT_V2=y -+CONFIG_FUSE_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_PSTORE=y -+CONFIG_PSTORE_CONSOLE=y -+CONFIG_PSTORE_RAM=y -+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y -+CONFIG_SECURITY=y -+CONFIG_SECURITY_NETWORK=y -+CONFIG_HARDENED_USERCOPY=y -+CONFIG_SECURITY_SELINUX=y -+CONFIG_CRYPTO_ADIANTUM=y -+CONFIG_CRYPTO_SHA512=y -+CONFIG_CRYPTO_LZ4=y -+CONFIG_CRYPTO_ZSTD=y -+CONFIG_CRYPTO_ANSI_CPRNG=y -+CONFIG_CRYPTO_DEV_VIRTIO=y -+CONFIG_CRC8=y -+CONFIG_XZ_DEC=y -+CONFIG_PRINTK_TIME=y -+CONFIG_DEBUG_INFO=y -+# CONFIG_ENABLE_MUST_CHECK is not set -+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -+CONFIG_MAGIC_SYSRQ=y -+CONFIG_DEBUG_STACK_USAGE=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_SOFTLOCKUP_DETECTOR=y -+# CONFIG_DETECT_HUNG_TASK is not set -+CONFIG_PANIC_TIMEOUT=5 -+CONFIG_SCHEDSTATS=y -+# CONFIG_RUNTIME_TESTING_MENU is not set -+CONFIG_UNWINDER_FRAME_POINTER=y -diff --git a/build.config.gki.x86_64 b/build.config.gki.x86_64 -new file mode 100644 -index 000000000000..69d339dce4a0 ---- /dev/null -+++ b/build.config.gki.x86_64 -@@ -0,0 +1,17 @@ -+ARCH=x86_64 -+BRANCH=android-mainline -+CLANG_TRIPLE=x86_64-linux-gnu- -+CROSS_COMPILE=x86_64-linux-androidkernel- -+CC=clang -+DEFCONFIG=gki_defconfig -+EXTRA_CMDS='' -+KERNEL_DIR=common -+POST_DEFCONFIG_CMDS="check_defconfig" -+CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin -+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin -+FILES=" -+arch/x86/boot/bzImage -+vmlinux -+System.map -+" -+STOP_SHIP_TRACEPRINTK=1 diff --git a/patches/ANDROID-Add-show_options2-to-view-private-mount-data.patch b/patches/ANDROID-Add-show_options2-to-view-private-mount-data.patch deleted file mode 100644 index 2ec7a16cbd86f05abc0f601a2ed552258b6d5810..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Add-show_options2-to-view-private-mount-data.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Tue, 16 Jul 2019 18:09:39 -0700 -Subject: ANDROID: Add show_options2 to view private mount data - -Exposes private fs data via show_options2 - -Bug: 120446149 -Change-Id: I2d1c06fae274eeac03ac1924ef162f7bbb2f29d0 -Signed-off-by: Daniel Rosenberg ---- - fs/proc_namespace.c | 8 ++++++-- - include/linux/fs.h | 1 + - 2 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c -index 273ee82d8aa9..5b8d065fa83c 100644 ---- a/fs/proc_namespace.c -+++ b/fs/proc_namespace.c -@@ -121,7 +121,9 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt) - if (err) - goto out; - show_mnt_opts(m, mnt); -- if (sb->s_op->show_options) -+ if (sb->s_op->show_options2) -+ err = sb->s_op->show_options2(mnt, m, mnt_path.dentry); -+ else if (sb->s_op->show_options) - err = sb->s_op->show_options(m, mnt_path.dentry); - seq_puts(m, " 0 0\n"); - out: -@@ -183,7 +185,9 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) - err = show_sb_opts(m, sb); - if (err) - goto out; -- if (sb->s_op->show_options) -+ if (sb->s_op->show_options2) { -+ err = sb->s_op->show_options2(mnt, m, mnt->mnt_root); -+ } else if (sb->s_op->show_options) - err = sb->s_op->show_options(m, mnt->mnt_root); - seq_putc(m, '\n'); - out: -diff --git a/include/linux/fs.h b/include/linux/fs.h -index 42c2cfc33ce7..eccf96ceef3b 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1965,6 +1965,7 @@ struct super_operations { - void (*umount_begin) (struct super_block *); - - int (*show_options)(struct seq_file *, struct dentry *); -+ int (*show_options2)(struct vfsmount *,struct seq_file *, struct dentry *); - int (*show_devname)(struct seq_file *, struct dentry *); - int (*show_path)(struct seq_file *, struct dentry *); - int (*show_stats)(struct seq_file *, struct dentry *); diff --git a/patches/ANDROID-Adding-GKI-Ramdisk-to-gki-config.patch b/patches/ANDROID-Adding-GKI-Ramdisk-to-gki-config.patch deleted file mode 100644 index 6b4cd338f73d961201ec45d81bed89598892368a..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Adding-GKI-Ramdisk-to-gki-config.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Tue, 13 Aug 2019 10:11:28 -0700 -Subject: ANDROID: Adding GKI Ramdisk to gki config - -Test: Treehugger -Bug: 132629930 -Change-Id: I3773d828cea4ab0ea8cfaef8a533a5ae925f037c -Signed-of-by: Ram Muthiah ---- - build.config.gki.aarch64 | 1 + - build.config.gki.x86_64 | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 -index 79871cdc6d07..653e82bf1965 100644 ---- a/build.config.gki.aarch64 -+++ b/build.config.gki.aarch64 -@@ -16,3 +16,4 @@ vmlinux - System.map - " - STOP_SHIP_TRACEPRINTK=1 -+BUILD_INITRAMFS=1 -diff --git a/build.config.gki.x86_64 b/build.config.gki.x86_64 -index b5a7f4600101..5c2db37a2871 100644 ---- a/build.config.gki.x86_64 -+++ b/build.config.gki.x86_64 -@@ -16,3 +16,4 @@ vmlinux - System.map - " - STOP_SHIP_TRACEPRINTK=1 -+BUILD_INITRAMFS=1 diff --git a/patches/ANDROID-Adding-SERIAL_OF_PLATFORM-module-to-gki.patch b/patches/ANDROID-Adding-SERIAL_OF_PLATFORM-module-to-gki.patch deleted file mode 100644 index 7bc37b983f99c56bff54c86adf68e62c28135a39..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Adding-SERIAL_OF_PLATFORM-module-to-gki.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Wed, 4 Sep 2019 16:18:17 -0700 -Subject: ANDROID: Adding SERIAL_OF_PLATFORM module to gki - -Bug: 132629930 -Change-Id: I722540edb8b7a7289e45e63de2959399cb563e23 -Signed-off-by: Ram Muthiah ---- - arch/arm64/configs/gki_defconfig | 2 +- - arch/x86/configs/gki_defconfig | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 6aae6d55e96c..d650f7d141e7 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -268,7 +268,7 @@ CONFIG_SERIAL_8250_NR_UARTS=48 - CONFIG_SERIAL_8250_EXTENDED=y - CONFIG_SERIAL_8250_MANY_PORTS=y - CONFIG_SERIAL_8250_SHARE_IRQ=y --CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_OF_PLATFORM=m - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_VIRTIO_CONSOLE=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index b3dad521ee8a..511a763add37 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -170,6 +170,7 @@ CONFIG_RFKILL=y - CONFIG_PCI=y - # CONFIG_ALLOW_DEV_COREDUMP is not set - CONFIG_DEBUG_DEVRES=y -+CONFIG_OF=y - CONFIG_ZRAM=y - CONFIG_BLK_DEV_LOOP=y - CONFIG_BLK_DEV_RAM=y -@@ -240,6 +241,7 @@ CONFIG_SERIAL_8250_NR_UARTS=48 - CONFIG_SERIAL_8250_EXTENDED=y - CONFIG_SERIAL_8250_MANY_PORTS=y - CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_OF_PLATFORM=m - CONFIG_HW_RANDOM=y - CONFIG_HW_RANDOM_VIRTIO=m - # CONFIG_I2C_COMPAT is not set diff --git a/patches/ANDROID-CONFIG_MMC-m.patch b/patches/ANDROID-CONFIG_MMC-m.patch deleted file mode 100644 index 228f12394bbdf2359bf778a46975d3801f3444e5..0000000000000000000000000000000000000000 --- a/patches/ANDROID-CONFIG_MMC-m.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Salyzyn -Date: Thu, 12 Sep 2019 14:06:44 -0700 -Subject: ANDROID: CONFIG_MMC=m - -Signed-off-by: Mark Salyzyn -Test: compile -Bug: 140652382 -Change-Id: Ie6002cde4d964920c71edd347851df9ceec4ee0f -(cherry picked from commit 30f8bea960e42921156a401e8e8ddb80fa3ee5c6) ---- - arch/arm64/configs/gki_defconfig | 6 +++--- - arch/x86/configs/gki_defconfig | 3 +-- - 2 files changed, 4 insertions(+), 5 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index ea9960028cfd..440173b3c301 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -323,11 +323,11 @@ CONFIG_USB_CONFIGFS_F_FS=y - CONFIG_USB_CONFIGFS_F_ACC=y - CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y - CONFIG_USB_CONFIGFS_F_MIDI=y --CONFIG_MMC=y -+CONFIG_MMC=m - # CONFIG_PWRSEQ_EMMC is not set - # CONFIG_PWRSEQ_SIMPLE is not set --CONFIG_MMC_SDHCI=y --CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI=m -+CONFIG_MMC_SDHCI_PLTFM=m - CONFIG_NEW_LEDS=y - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index a5953d43d480..c206a2d0f9cf 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -280,8 +280,7 @@ CONFIG_USB_CONFIGFS_F_FS=y - CONFIG_USB_CONFIGFS_F_ACC=y - CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y - CONFIG_USB_CONFIGFS_F_MIDI=y --CONFIG_MMC=y --# CONFIG_MMC_BLOCK is not set -+CONFIG_MMC=m - CONFIG_NEW_LEDS=y - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y diff --git a/patches/ANDROID-Catch-rockpi4_defconfig-up-with-gki_defconfig.patch b/patches/ANDROID-Catch-rockpi4_defconfig-up-with-gki_defconfig.patch deleted file mode 100644 index 008a680fe83b851e5515fba8d7d7b5635cd08400..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Catch-rockpi4_defconfig-up-with-gki_defconfig.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Delva -Date: Wed, 4 Sep 2019 12:25:57 -0700 -Subject: ANDROID: Catch rockpi4_defconfig up with gki_defconfig - -Change-Id: I640112a903d0b4944a087a4408241b901f37f6b8 -Signed-off-by: Alistair Delva ---- - arch/arm64/configs/rockpi4_defconfig | 31 +++++++++++++++------------- - 1 file changed, 17 insertions(+), 14 deletions(-) - -diff --git a/arch/arm64/configs/rockpi4_defconfig b/arch/arm64/configs/rockpi4_defconfig -index 6d0cf70f3757..2f97c1a8a60a 100644 ---- a/arch/arm64/configs/rockpi4_defconfig -+++ b/arch/arm64/configs/rockpi4_defconfig -@@ -1,3 +1,4 @@ -+CONFIG_LOCALVERSION="-mainline" - CONFIG_AUDIT=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y -@@ -24,7 +25,6 @@ CONFIG_BLK_DEV_INITRD=y - # CONFIG_RD_LZO is not set - # CONFIG_RD_LZ4 is not set - # CONFIG_SYSFS_SYSCALL is not set --CONFIG_FHANDLE=y - CONFIG_KALLSYMS_ALL=y - CONFIG_BPF_SYSCALL=y - # CONFIG_RSEQ is not set -@@ -35,8 +35,10 @@ CONFIG_EMBEDDED=y - CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y -+CONFIG_ARCH_QCOM=y - CONFIG_ARCH_ROCKCHIP=y - CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=32 - CONFIG_SECCOMP=y - CONFIG_PARAVIRT=y - CONFIG_COMPAT=y -@@ -45,9 +47,7 @@ CONFIG_SWP_EMULATION=y - CONFIG_CP15_BARRIER_EMULATION=y - CONFIG_SETEND_EMULATION=y - CONFIG_RANDOMIZE_BASE=y --CONFIG_CMDLINE="" --# CONFIG_CMDLINE_FORCE is not set --# CONFIG_EFI is not set -+# CONFIG_DMI is not set - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set -@@ -65,6 +65,7 @@ CONFIG_ARM_SCMI_PROTOCOL=y - # CONFIG_ARM_SCMI_POWER_DOMAIN is not set - CONFIG_ARM_SCPI_PROTOCOL=y - # CONFIG_ARM_SCPI_POWER_DOMAIN is not set -+# CONFIG_EFI_ARMSTUB_DTB_LOADER is not set - CONFIG_VIRTUALIZATION=y - CONFIG_KVM=y - CONFIG_VHOST_VSOCK=y -@@ -93,7 +94,6 @@ CONFIG_INET=y - CONFIG_IP_MULTICAST=y - CONFIG_IP_ADVANCED_ROUTER=y - CONFIG_IP_MULTIPLE_TABLES=y --CONFIG_IP_PNP=y - CONFIG_NET_IPGRE_DEMUX=y - CONFIG_NET_IPVTI=y - CONFIG_INET_ESP=y -@@ -108,6 +108,7 @@ CONFIG_IPV6_MIP6=y - CONFIG_IPV6_VTI=y - CONFIG_IPV6_MULTIPLE_TABLES=y - CONFIG_NETFILTER=y -+# CONFIG_BRIDGE_NETFILTER is not set - CONFIG_NF_CONNTRACK=y - CONFIG_NF_CONNTRACK_SECMARK=y - CONFIG_NF_CONNTRACK_EVENTS=y -@@ -176,6 +177,7 @@ CONFIG_IP6_NF_FILTER=y - 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_NET_SCHED=y -@@ -376,7 +378,6 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV=y - CONFIG_DW_WATCHDOG=y - CONFIG_MFD_ACT8945A=y - CONFIG_MFD_RK808=y --CONFIG_REGULATOR=y - CONFIG_REGULATOR_DEBUG=y - CONFIG_REGULATOR_FIXED_VOLTAGE=y - CONFIG_REGULATOR_VIRTUAL_CONSUMER=y -@@ -388,7 +389,6 @@ CONFIG_REGULATOR_VCTRL=y - CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_CONTROLLER=y --CONFIG_VIDEO_V4L2_SUBDEV_API=y - # CONFIG_VGA_ARB is not set - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set -@@ -397,7 +397,6 @@ CONFIG_ROCKCHIP_DW_HDMI=y - CONFIG_DRM_VIRTIO_GPU=y - # CONFIG_LCD_CLASS_DEVICE is not set - CONFIG_BACKLIGHT_CLASS_DEVICE=y --# CONFIG_BACKLIGHT_GENERIC is not set - CONFIG_SOUND=y - CONFIG_SND=y - CONFIG_SND_HRTIMER=y -@@ -427,6 +426,7 @@ CONFIG_USB_OHCI_HCD=y - # CONFIG_USB_OHCI_HCD_PCI is not set - CONFIG_USB_OHCI_HCD_PLATFORM=y - CONFIG_USB_GADGET=y -+CONFIG_USB_DUMMY_HCD=m - CONFIG_USB_CONFIGFS=y - CONFIG_USB_CONFIGFS_UEVENT=y - CONFIG_USB_CONFIGFS_F_FS=y -@@ -442,10 +442,10 @@ CONFIG_MMC_SDHCI_OF_ARASAN=y - CONFIG_MMC_SDHCI_OF_DWCMSHC=y - CONFIG_MMC_DW=y - CONFIG_MMC_DW_ROCKCHIP=y --CONFIG_MMC_CQHCI=y - CONFIG_NEW_LEDS=y - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y -+CONFIG_EDAC=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_SYSTOHC is not set - CONFIG_RTC_DRV_RK808=y -@@ -462,16 +462,17 @@ CONFIG_STAGING=y - CONFIG_ASHMEM=y - CONFIG_ANDROID_VSOC=y - CONFIG_ION=y -+CONFIG_ION_SYSTEM_HEAP=y -+CONFIG_ION_SYSTEM_CONTIG_HEAP=y - CONFIG_COMMON_CLK_RK808=y - CONFIG_COMMON_CLK_SCPI=y --# CONFIG_COMMON_CLK_XGENE is not set - CONFIG_HWSPINLOCK=y --# CONFIG_FSL_ERRATUM_A008585 is not set --# CONFIG_HISILICON_ERRATUM_161010101 is not set - CONFIG_MAILBOX=y - CONFIG_ROCKCHIP_MBOX=y - CONFIG_ROCKCHIP_IOMMU=y - CONFIG_ARM_SMMU=y -+CONFIG_QCOM_COMMAND_DB=y -+CONFIG_QCOM_RPMH=y - CONFIG_ROCKCHIP_PM_DOMAINS=y - CONFIG_DEVFREQ_GOV_PERFORMANCE=y - CONFIG_DEVFREQ_GOV_POWERSAVE=y -@@ -480,10 +481,12 @@ CONFIG_DEVFREQ_GOV_PASSIVE=y - CONFIG_ARM_RK3399_DMC_DEVFREQ=y - CONFIG_PWM=y - CONFIG_PWM_ROCKCHIP=y -+CONFIG_QCOM_PDC=y - CONFIG_PHY_ROCKCHIP_EMMC=y - CONFIG_PHY_ROCKCHIP_INNO_HDMI=y - CONFIG_PHY_ROCKCHIP_INNO_USB2=y - CONFIG_PHY_ROCKCHIP_USB=y -+CONFIG_RAS=y - CONFIG_ANDROID=y - CONFIG_ANDROID_BINDER_IPC=y - CONFIG_ROCKCHIP_EFUSE=y -@@ -500,9 +503,9 @@ CONFIG_FUSE_FS=y - CONFIG_OVERLAY_FS=y - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y --CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y --CONFIG_ECRYPT_FS=y -+# CONFIG_EFIVAR_FS is not set -+CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y - CONFIG_PSTORE_RAM=y diff --git a/patches/ANDROID-Expose-gki_defconfig-to-build.config.patch b/patches/ANDROID-Expose-gki_defconfig-to-build.config.patch deleted file mode 100644 index 29dc49ade84559c5bccd4f60e6919b5d60f1ad03..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Expose-gki_defconfig-to-build.config.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthias Maennich -Date: Wed, 8 May 2019 23:07:39 +0100 -Subject: ANDROID: Expose gki_defconfig to build.config - -With this in place, the gki_defconfig can be build with build.sh -machinery. - -Bug: 132113225 -Change-Id: I4c623a866cd41aa4587e4fab1c4e5254f6680542 -Signed-off-by: Matthias Maennich ---- - build.config.gki.aarch64 | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - create mode 100644 build.config.gki.aarch64 - -diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 -new file mode 100644 -index 000000000000..dec295284ffa ---- /dev/null -+++ b/build.config.gki.aarch64 -@@ -0,0 +1,17 @@ -+ARCH=arm64 -+BRANCH=android-mainline -+CLANG_TRIPLE=aarch64-linux-gnu- -+CROSS_COMPILE=aarch64-linux-androidkernel- -+CC=clang -+DEFCONFIG=gki_defconfig -+EXTRA_CMDS='' -+KERNEL_DIR=common -+POST_DEFCONFIG_CMDS="check_defconfig" -+CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r349610/bin -+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin -+FILES=" -+arch/arm64/boot/Image.gz -+vmlinux -+System.map -+" -+STOP_SHIP_TRACEPRINTK=1 diff --git a/patches/ANDROID-Fix-arm64-allmodconfig-build.patch b/patches/ANDROID-Fix-arm64-allmodconfig-build.patch deleted file mode 100644 index 320c7a5b3efe98e9f98ae120d34aa54889caf9c0..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Fix-arm64-allmodconfig-build.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Quentin Perret -Date: Tue, 24 Sep 2019 17:28:02 +0100 -Subject: ANDROID: Fix arm64 allmodconfig build - -Allmodconfig on arm64 enables CPU_BIG_ENDIAN=y, which causes issues with -ld.lld which doesn't support linking aarch64be-linux-gnu targets (see -https://reviews.llvm.org/D58655#1410281). However, it is very unlikely -that real android devices run with arm64 BE hardware in practice. So, -until we can find a better fix, let's simply force CPU_BIG_ENDIAN=n for -allmodconfig builds. - -Bug: 141733632 -Bug: 140224784 -Signed-off-by: Quentin Perret -Change-Id: Ic4693ae1f462144c8219b397463ca341f6fe08a1 ---- - build.config.allmodconfig | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/build.config.allmodconfig b/build.config.allmodconfig -index 6e0404b8de47..deaa8f3d5a69 100644 ---- a/build.config.allmodconfig -+++ b/build.config.allmodconfig -@@ -6,7 +6,8 @@ POST_DEFCONFIG_CMDS="update_config" - function update_config() { - ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \ - -d TEST_KMOD \ -- -d XFS_FS -+ -d XFS_FS \ -+ -d CPU_BIG_ENDIAN - (cd ${OUT_DIR} && \ - make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig) - } diff --git a/patches/ANDROID-Fix-x86_64-allmodconfig-build.patch b/patches/ANDROID-Fix-x86_64-allmodconfig-build.patch deleted file mode 100644 index fb81b8ce89a77d5076d98203c4075effaf0f4611..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Fix-x86_64-allmodconfig-build.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Delva -Date: Fri, 11 Oct 2019 10:24:23 -0400 -Subject: ANDROID: Fix x86_64 allmodconfig build - -CONFIG_KVM_INTEL depends on asm volatile goto which is about to be -supported in clang, but we haven't landed the upgraded compiler yet. -Suppress use of this kernel feature for now. - -In file included from arch/x86/kvm/vmx/vmx.h:11: -arch/x86/kvm/vmx/ops.h:157:2: error: 'asm goto' constructs are not -supported yet -vmx_asm2(vmwrite, "r"(field), "rm"(value), field, value); -^ - -Change-Id: If21ca65a7bd1e43c5f66a93a6108cf8aa49a9c64 -Signed-off-by: Alistair Delva ---- - build.config.allmodconfig | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/build.config.allmodconfig b/build.config.allmodconfig -index deaa8f3d5a69..854a8f8aa3f2 100644 ---- a/build.config.allmodconfig -+++ b/build.config.allmodconfig -@@ -2,12 +2,14 @@ DEFCONFIG=allmodconfig - KCONFIG_ALLCONFIG=${ROOT_DIR}/common/arch/${ARCH%_*}/configs/gki_defconfig - - # XFS_FS is currently broken on this branch with clang-9 -+# KVM_INTEL is broken on this branch due to lack of asm-goto support in clang - POST_DEFCONFIG_CMDS="update_config" - function update_config() { - ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \ - -d TEST_KMOD \ - -d XFS_FS \ -- -d CPU_BIG_ENDIAN -+ -d CPU_BIG_ENDIAN \ -+ -d KVM_INTEL - (cd ${OUT_DIR} && \ - make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig) - } diff --git a/patches/ANDROID-Fixed-x86-regression.patch b/patches/ANDROID-Fixed-x86-regression.patch deleted file mode 100644 index 3cb293ca6a8e5c7f594f70120844a4df559a6d0b..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Fixed-x86-regression.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Wed, 12 Jun 2019 14:25:25 -0700 -Subject: ANDROID: Fixed x86 regression - -Added SMP and CMDLINE to defconfig - -Test: Boot x86 gki -Change-Id: I6930d60dceb5b180825337d5371d375259984a33 -Signed-off-by: Ram Muthiah ---- - arch/x86/configs/gki_defconfig | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 864595c719e7..94690e9d016a 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -33,13 +33,14 @@ CONFIG_EMBEDDED=y - CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y -+CONFIG_SMP=y -+CONFIG_CMDLINE_BOOL=y -+CONFIG_CMDLINE="console=ttyS0 reboot=p" - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set --CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_TIMES=y - CONFIG_CPU_FREQ_GOV_POWERSAVE=y --CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y - CONFIG_IA32_EMULATION=y - CONFIG_KPROBES=y - CONFIG_MODULES=y -@@ -288,7 +289,6 @@ CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y - CONFIG_STAGING=y - CONFIG_ASHMEM=y - CONFIG_ION=y --CONFIG_MAILBOX=y - CONFIG_PM_DEVFREQ=y - CONFIG_ANDROID=y - CONFIG_ANDROID_BINDER_IPC=y diff --git a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-1-4.patch b/patches/ANDROID-Four-part-revert-of-asm-goto-usage-1-4.patch deleted file mode 100644 index 9e032432c74d013c7661de4545ef6acc16828580..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-1-4.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Tue, 21 May 2019 18:15:10 -0700 -Subject: ANDROID-Four-part-revert-of-asm-goto-usage-1-4 - -Revert "x86/uaccess: Dont leak the AC flag into __put_user() argument evaluation" -This reverts commit 6ae865615fc43d014da2fd1f1bba7e81ee622d1b. - -Bug: 120440614 -Bug: 132629930 -Change-Id: I38f78e20d255ab4b33546d2e9d98f64d7e590e1d -Signed-off-by: Ram Muthiah ---- - arch/x86/include/asm/uaccess.h | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h -index 61d93f062a36..176c73385605 100644 ---- a/arch/x86/include/asm/uaccess.h -+++ b/arch/x86/include/asm/uaccess.h -@@ -429,11 +429,10 @@ do { \ - ({ \ - __label__ __pu_label; \ - int __pu_err = -EFAULT; \ -- __typeof__(*(ptr)) __pu_val = (x); \ -- __typeof__(ptr) __pu_ptr = (ptr); \ -- __typeof__(size) __pu_size = (size); \ -+ __typeof__(*(ptr)) __pu_val; \ -+ __pu_val = x; \ - __uaccess_begin(); \ -- __put_user_size(__pu_val, __pu_ptr, __pu_size, __pu_label); \ -+ __put_user_size(__pu_val, (ptr), (size), __pu_label); \ - __pu_err = 0; \ - __pu_label: \ - __uaccess_end(); \ diff --git a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-2-4.patch b/patches/ANDROID-Four-part-revert-of-asm-goto-usage-2-4.patch deleted file mode 100644 index 0a0f4b1312940bd939e25886530bd4bb5dbef4ba..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-2-4.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Tue, 21 May 2019 18:15:21 -0700 -Subject: ANDROID-Four-part-revert-of-asm-goto-usage-2-4 - -Revert "x86/uaccess: Don't leak the AC flag into __put_user() value evaluation" -This reverts commit 2a418cf3f5f1caf911af288e978d61c9844b0695. - -Bug: 120440614 -Bug: 132629930 -Change-Id: Ib177230b39d1247060f425205d63d65065ed936a -Signed-off-by: Ram Muthiah ---- - arch/x86/include/asm/uaccess.h | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h -index 176c73385605..8fc40674c174 100644 ---- a/arch/x86/include/asm/uaccess.h -+++ b/arch/x86/include/asm/uaccess.h -@@ -282,7 +282,7 @@ do { \ - __put_user_goto(x, ptr, "l", "k", "ir", label); \ - break; \ - case 8: \ -- __put_user_goto_u64(x, ptr, label); \ -+ __put_user_goto_u64((__typeof__(*ptr))(x), ptr, label); \ - break; \ - default: \ - __put_user_bad(); \ -@@ -429,10 +429,8 @@ do { \ - ({ \ - __label__ __pu_label; \ - int __pu_err = -EFAULT; \ -- __typeof__(*(ptr)) __pu_val; \ -- __pu_val = x; \ - __uaccess_begin(); \ -- __put_user_size(__pu_val, (ptr), (size), __pu_label); \ -+ __put_user_size((x), (ptr), (size), __pu_label); \ - __pu_err = 0; \ - __pu_label: \ - __uaccess_end(); \ diff --git a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-3-4.patch b/patches/ANDROID-Four-part-revert-of-asm-goto-usage-3-4.patch deleted file mode 100644 index fca66a066ddbf1070642dcb46b4e842798af5917..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-3-4.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Tue, 21 May 2019 18:20:17 -0700 -Subject: ANDROID-Four-part-revert-of-asm-goto-usage-3-4 - -Revert "Use __put_user_goto in __put_user_size() and unsafe_put_user()" -This reverts commit a959dc88f9c8900296ccf13e2f3e1cbc555a8917. - -Bug: 120440614 -Bug: 132629930 -Change-Id: I07410ed2bc7552f16ec119fbc2001bb43ffef6f4 -Signed-off-by: Ram Muthiah ---- - arch/x86/include/asm/uaccess.h | 57 ++++++++++++++++++++-------------- - 1 file changed, 33 insertions(+), 24 deletions(-) - -diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h -index 8fc40674c174..0b049e6baf31 100644 ---- a/arch/x86/include/asm/uaccess.h -+++ b/arch/x86/include/asm/uaccess.h -@@ -184,14 +184,19 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) - - - #ifdef CONFIG_X86_32 --#define __put_user_goto_u64(x, addr, label) \ -- asm_volatile_goto("\n" \ -- "1: movl %%eax,0(%1)\n" \ -- "2: movl %%edx,4(%1)\n" \ -- _ASM_EXTABLE_UA(1b, %l2) \ -- _ASM_EXTABLE_UA(2b, %l2) \ -- : : "A" (x), "r" (addr) \ -- : : label) -+#define __put_user_asm_u64(x, addr, err, errret) \ -+ asm volatile("\n" \ -+ "1: movl %%eax,0(%2)\n" \ -+ "2: movl %%edx,4(%2)\n" \ -+ "3:" \ -+ ".section .fixup,\"ax\"\n" \ -+ "4: movl %3,%0\n" \ -+ " jmp 3b\n" \ -+ ".previous\n" \ -+ _ASM_EXTABLE_UA(1b, 4b) \ -+ _ASM_EXTABLE_UA(2b, 4b) \ -+ : "=r" (err) \ -+ : "A" (x), "r" (addr), "i" (errret), "0" (err)) - - #define __put_user_asm_ex_u64(x, addr) \ - asm volatile("\n" \ -@@ -206,8 +211,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) - asm volatile("call __put_user_8" : "=a" (__ret_pu) \ - : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") - #else --#define __put_user_goto_u64(x, ptr, label) \ -- __put_user_goto(x, ptr, "q", "", "er", label) -+#define __put_user_asm_u64(x, ptr, retval, errret) \ -+ __put_user_asm(x, ptr, retval, "q", "", "er", errret) - #define __put_user_asm_ex_u64(x, addr) \ - __put_user_asm_ex(x, addr, "q", "", "er") - #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu) -@@ -268,21 +273,23 @@ extern void __put_user_8(void); - __builtin_expect(__ret_pu, 0); \ - }) - --#define __put_user_size(x, ptr, size, label) \ -+#define __put_user_size(x, ptr, size, retval, errret) \ - do { \ -+ retval = 0; \ - __chk_user_ptr(ptr); \ - switch (size) { \ - case 1: \ -- __put_user_goto(x, ptr, "b", "b", "iq", label); \ -+ __put_user_asm(x, ptr, retval, "b", "b", "iq", errret); \ - break; \ - case 2: \ -- __put_user_goto(x, ptr, "w", "w", "ir", label); \ -+ __put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \ - break; \ - case 4: \ -- __put_user_goto(x, ptr, "l", "k", "ir", label); \ -+ __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \ - break; \ - case 8: \ -- __put_user_goto_u64((__typeof__(*ptr))(x), ptr, label); \ -+ __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \ -+ errret); \ - break; \ - default: \ - __put_user_bad(); \ -@@ -427,12 +434,9 @@ do { \ - - #define __put_user_nocheck(x, ptr, size) \ - ({ \ -- __label__ __pu_label; \ -- int __pu_err = -EFAULT; \ -+ int __pu_err; \ - __uaccess_begin(); \ -- __put_user_size((x), (ptr), (size), __pu_label); \ -- __pu_err = 0; \ --__pu_label: \ -+ __put_user_size((x), (ptr), (size), __pu_err, -EFAULT); \ - __uaccess_end(); \ - __builtin_expect(__pu_err, 0); \ - }) -@@ -716,11 +720,16 @@ static __must_check __always_inline bool user_access_begin(const void __user *pt - #define user_access_begin(a,b) user_access_begin(a,b) - #define user_access_end() __uaccess_end() - --#define user_access_save() smap_save() --#define user_access_restore(x) smap_restore(x) -+#define user_access_save() smap_save() -+#define user_access_restore(x) smap_restore(x) - --#define unsafe_put_user(x, ptr, label) \ -- __put_user_size((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), label) -+#define unsafe_put_user(x, ptr, err_label) \ -+do { \ -+ int __pu_err; \ -+ __typeof__(*(ptr)) __pu_val = (x); \ -+ __put_user_size(__pu_val, (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \ -+ if (unlikely(__pu_err)) goto err_label; \ -+} while (0) - - #define unsafe_get_user(x, ptr, err_label) \ - do { \ diff --git a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-4-4.patch b/patches/ANDROID-Four-part-revert-of-asm-goto-usage-4-4.patch deleted file mode 100644 index fba76ae57b9b6287d2825033e991e598cb8627a8..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Four-part-revert-of-asm-goto-usage-4-4.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Tue, 21 May 2019 18:21:54 -0700 -Subject: ANDROID-Four-part-revert-of-asm-goto-usage-4-4 - -Revert "x86 uaccess: Introduce __put_user_goto" -This reverts commit 4a789213c9a54c8b618924d3421e56e98df8a447. - -Bug: 120440614 -Bug: 132629930 -Change-Id: If5e90d475d74d9aa3505972f43bc4ee48bed038f -Signed-off-by: Ram Muthiah ---- - arch/x86/include/asm/uaccess.h | 28 +++++++++++----------------- - 1 file changed, 11 insertions(+), 17 deletions(-) - -diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h -index 0b049e6baf31..d3b6c3ba61d1 100644 ---- a/arch/x86/include/asm/uaccess.h -+++ b/arch/x86/include/asm/uaccess.h -@@ -463,23 +463,17 @@ struct __large_struct { unsigned long buf[100]; }; - * we do not write to any memory gcc knows about, so there are no - * aliasing issues. - */ --#define __put_user_goto(x, addr, itype, rtype, ltype, label) \ -- asm_volatile_goto("\n" \ -- "1: mov"itype" %"rtype"0,%1\n" \ -- _ASM_EXTABLE_UA(1b, %l2) \ -- : : ltype(x), "m" (__m(addr)) \ -- : : label) -- --#define __put_user_failed(x, addr, itype, rtype, ltype, errret) \ -- ({ __label__ __puflab; \ -- int __pufret = errret; \ -- __put_user_goto(x,addr,itype,rtype,ltype,__puflab); \ -- __pufret = 0; \ -- __puflab: __pufret; }) -- --#define __put_user_asm(x, addr, retval, itype, rtype, ltype, errret) do { \ -- retval = __put_user_failed(x, addr, itype, rtype, ltype, errret); \ --} while (0) -+#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ -+ asm volatile("\n" \ -+ "1: mov"itype" %"rtype"1,%2\n" \ -+ "2:\n" \ -+ ".section .fixup,\"ax\"\n" \ -+ "3: mov %3,%0\n" \ -+ " jmp 2b\n" \ -+ ".previous\n" \ -+ _ASM_EXTABLE_UA(1b, 3b) \ -+ : "=r"(err) \ -+ : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err)) - - #define __put_user_asm_ex(x, addr, itype, rtype, ltype) \ - asm volatile("1: mov"itype" %"rtype"0,%1\n" \ diff --git a/patches/ANDROID-GKI-enable-CONFIG_SPI-for-x86.patch b/patches/ANDROID-GKI-enable-CONFIG_SPI-for-x86.patch deleted file mode 100644 index ca971212a9296bee2d95a6364b8ebbe6e810ac5b..0000000000000000000000000000000000000000 --- a/patches/ANDROID-GKI-enable-CONFIG_SPI-for-x86.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Salyzyn -Date: Tue, 3 Sep 2019 09:42:35 -0700 -Subject: ANDROID: GKI: enable CONFIG_SPI for x86 - -Adds compile coverage for SPI in the TH builds, runtime no so much. - -Signed-off-by: Mark Salyzyn -Bug: 140290328 -Change-Id: I2d7777ab0e671248084880e5c1770b6ec6d7a650 ---- - arch/x86/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index e86cd1009a67..9b76d55e8c41 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -240,6 +240,7 @@ CONFIG_HW_RANDOM=y - CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_I2C_COMPAT is not set - # CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_SPI=y - CONFIG_GPIOLIB=y - # CONFIG_HWMON is not set - CONFIG_DEVFREQ_THERMAL=y diff --git a/patches/ANDROID-GKI-enable-CONFIG_TIPC-for-x86.patch b/patches/ANDROID-GKI-enable-CONFIG_TIPC-for-x86.patch deleted file mode 100644 index f478aa67e56931cf98504b50b5e2c62abe116c41..0000000000000000000000000000000000000000 --- a/patches/ANDROID-GKI-enable-CONFIG_TIPC-for-x86.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Salyzyn -Date: Tue, 3 Sep 2019 13:17:23 -0700 -Subject: ANDROID: GKI: enable CONFIG_TIPC for x86 - -Adds compile coverage for TIPC in the TH builds, runtime not so much. - -Signed-off-by: Mark Salyzyn -Bug: 140406060 -Change-Id: I7731157396372683c906f1f4eb2fdbdb7015f446 ---- - arch/x86/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 9b76d55e8c41..6b0ff4ca236a 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -145,6 +145,7 @@ CONFIG_IP6_NF_FILTER=y - CONFIG_IP6_NF_TARGET_REJECT=y - CONFIG_IP6_NF_MANGLE=y - CONFIG_IP6_NF_RAW=y -+CONFIG_TIPC=y - CONFIG_L2TP=y - CONFIG_NET_SCHED=y - CONFIG_NET_SCH_HTB=y diff --git a/patches/ANDROID-GKI-export-cma-symbols-for-cma-heap-as-a-module.patch b/patches/ANDROID-GKI-export-cma-symbols-for-cma-heap-as-a-module.patch deleted file mode 100644 index 750af25c2d1e693d0c4af0f82e4c69b985bd3742..0000000000000000000000000000000000000000 --- a/patches/ANDROID-GKI-export-cma-symbols-for-cma-heap-as-a-module.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Fri, 13 Sep 2019 14:50:38 -0700 -Subject: ANDROID: GKI: export cma symbols for cma heap as a module - -Bug: 140294230 -Test: builds - -Change-Id: I04c12174934c24a704d5c1e5be3e7e948c777a78 -Signed-off-by: Sandeep Patil ---- - mm/cma.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/mm/cma.c b/mm/cma.c -index 7fe0b8356775..db4642e58058 100644 ---- a/mm/cma.c -+++ b/mm/cma.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -54,6 +55,7 @@ const char *cma_get_name(const struct cma *cma) - { - return cma->name ? cma->name : "(undefined)"; - } -+EXPORT_SYMBOL_GPL(cma_get_name); - - static unsigned long cma_bitmap_aligned_mask(const struct cma *cma, - unsigned int align_order) -@@ -500,6 +502,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, - pr_debug("%s(): returned %p\n", __func__, page); - return page; - } -+EXPORT_SYMBOL_GPL(cma_alloc); - - /** - * cma_release() - release allocated pages -@@ -533,6 +536,7 @@ bool cma_release(struct cma *cma, const struct page *pages, unsigned int count) - - return true; - } -+EXPORT_SYMBOL_GPL(cma_release); - - int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data) - { -@@ -547,3 +551,4 @@ int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data) - - return 0; - } -+EXPORT_SYMBOL_GPL(cma_for_each_area); diff --git a/patches/ANDROID-Initial-abi_gki_aarch64-definition.patch b/patches/ANDROID-Initial-abi_gki_aarch64-definition.patch deleted file mode 100644 index ca1290799e7ceb42f38fd43f7218b9b6c4af0f23..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Initial-abi_gki_aarch64-definition.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthias Maennich -Date: Tue, 28 May 2019 12:38:16 +0100 -Subject: ANDROID: Initial abi_gki_aarch64 definition - -abi_gki_aarch64.out contains the ABI definition corresponding to the -current sources and the configuration referred to in -build.config.gki.aarch64. - -As part of the build.sh tooling it will be copied over into the -distribution for further inspection / analysis. See -https://android-review.googlesource.com/970737 for details on that -process. - -This is the initial version of this definition to allow implementation -of workflows around it. It is not considered stable at this point. It is -expected that it will break with significant changes from either -upstream or with changes implemented specific for this tree. Automated -validation is supposed to catch differences between this definition and -the actual binary before they are introduced into the tree. At a later -stage this validation should be part of build.sh itself. - -Bug: 133501930 -Change-Id: I815940ee13037ad450547e0ab0786e37f0b83d9b -Signed-off-by: Matthias Maennich ---- - build.config.gki.aarch64 | 24 +++++------------------- - 1 file changed, 5 insertions(+), 19 deletions(-) - -diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 -index 653e82bf1965..352a6382b06c 100644 ---- a/build.config.gki.aarch64 -+++ b/build.config.gki.aarch64 -@@ -1,19 +1,5 @@ --ARCH=arm64 --BRANCH=android-mainline --CLANG_TRIPLE=aarch64-linux-gnu- --CROSS_COMPILE=aarch64-linux-androidkernel- --CC=clang --DEFCONFIG=gki_defconfig --EXTRA_CMDS='' --KERNEL_DIR=common --POST_DEFCONFIG_CMDS="check_defconfig" --CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin --BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 --LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin --FILES=" --arch/arm64/boot/Image.gz --vmlinux --System.map --" --STOP_SHIP_TRACEPRINTK=1 --BUILD_INITRAMFS=1 -+. ${ROOT_DIR}/common/build.config.common -+. ${ROOT_DIR}/common/build.config.aarch64 -+. ${ROOT_DIR}/common/build.config.gki -+ -+ABI_DEFINITION=abi_gki_aarch64.xml diff --git a/patches/ANDROID-Kbuild-LLVMLinux-allow-overriding-clang-target-triple.patch b/patches/ANDROID-Kbuild-LLVMLinux-allow-overriding-clang-target-triple.patch deleted file mode 100644 index 07a260d4ab43b900cd7cc0d226d2275ef300153b..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Kbuild-LLVMLinux-allow-overriding-clang-target-triple.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Greg Hackmann -Date: Tue, 25 Oct 2016 13:59:59 -0700 -Subject: ANDROID: Kbuild, LLVMLinux: allow overriding clang target triple - -Android has an unusual setup where the kernel needs to target -[arch]-linux-gnu to avoid Android userspace-specific flags and -optimizations, but AOSP doesn't ship a matching binutils. - -Add a new variable CLANG_TRIPLE which can override the "-target" triple -used to compile the kernel, while using a different CROSS_COMPILE to -pick the binutils/gcc installation. For Android you'd do something -like: - - export CLANG_TRIPLE=aarch64-linux-gnu- - export CROSS_COMPILE=aarch64-linux-android- - -If you don't need something like this, leave CLANG_TRIPLE unset and it -will default to CROSS_COMPILE. - -Change-Id: I85d63599c6ab8ed458071cdf9197d85b1f7f150b -Signed-off-by: Greg Hackmann -[astrachan: Added a script to check for incorrectly falling back to the - default when CLANG_TRIPLE is unset] -Bug: 118439987 -Bug: 120440614 -Test: make CLANG_TRIPLE=x86_64-linux-gnu CC=clang -Signed-off-by: Alistair Strachan ---- - Makefile | 6 +++++- - scripts/clang-android.sh | 4 ++++ - 2 files changed, 9 insertions(+), 1 deletion(-) - create mode 100644 scripts/clang-android.sh - -diff --git a/Makefile b/Makefile -index ffd7a912fc46..dd248a6159ee 100644 ---- a/Makefile -+++ b/Makefile -@@ -526,7 +526,11 @@ endif - - ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) - ifneq ($(CROSS_COMPILE),) --CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) -+CLANG_TRIPLE ?= $(CROSS_COMPILE) -+CLANG_FLAGS += --target=$(notdir $(CLANG_TRIPLE:%-=%)) -+ifeq ($(shell $(srctree)/scripts/clang-android.sh $(CC) $(CLANG_FLAGS)), y) -+$(error "Clang with Android --target detected. Did you specify CLANG_TRIPLE?") -+endif - GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit)) - CLANG_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR) - GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..) -diff --git a/scripts/clang-android.sh b/scripts/clang-android.sh -new file mode 100644 -index 000000000000..9186c4f48576 ---- /dev/null -+++ b/scripts/clang-android.sh -@@ -0,0 +1,4 @@ -+#!/bin/sh -+# SPDX-License-Identifier: GPL-2.0 -+ -+$* -dM -E - &1 | grep -q __ANDROID__ && echo "y" diff --git a/patches/ANDROID-Log-which-device-failed-to-suspend-in-dpm_suspend_start.patch b/patches/ANDROID-Log-which-device-failed-to-suspend-in-dpm_suspend_start.patch deleted file mode 100644 index cf4824b4a27db4847a2f3cdcd62fcf777bc1ac7c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Log-which-device-failed-to-suspend-in-dpm_suspend_start.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zhuguangqing -Date: Fri, 23 Aug 2019 09:04:06 +0800 -Subject: ANDROID: Log which device failed to suspend in dpm_suspend_start() - -Problem background: In the process of suspend, maybe some device suspend -callback failed in dpm_suspend_start()/dpm_prepare()/dpm_suspend(). -Because it's after suspend_console(), so printf() is disabled now. -Currently we can see "Some devices failed to suspend, or early wake -event detected" by log_suspend_abort_reason() in bugreport. There are -many devices but we don't know which exactly device failed. So we -want to do a little change to record which device failed. - -Note: I checked upstream LTS kernel, then I found the -patch can not be sent upstream, because it uses function -log_suspend_abort_reason() in wakeup_reason.c, the initial -patch(https://patchwork.kernel.org/patch/3827331/) for adding -/kernel/power/wakeup_reason.c is not accepted by upstream which -was merged in AOSP common kernels. So maybe the patch could -only be sent to AOSP common kernels. - -Test: manual - Use modified version for daily use two days, from -bugreport we can see which device failed. -Bug: 120445600 -Change-Id: I326c87ca1263496db79d08ec615f12fc22452d7a -Signed-off-by: zhuguangqing ---- - drivers/base/power/main.c | 1 + - kernel/power/suspend.c | 7 +++++-- - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c -index f545b4526172..40657d602be6 100644 ---- a/drivers/base/power/main.c -+++ b/drivers/base/power/main.c -@@ -1996,6 +1996,7 @@ int dpm_prepare(pm_message_t state) - } - pr_info("Device %s not prepared for power transition: code %d\n", - dev_name(dev), error); -+ dpm_save_failed_dev(dev_name(dev)); - put_device(dev); - break; - } -diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c -index de6b24bc0619..0bb1c1d8c979 100644 ---- a/kernel/power/suspend.c -+++ b/kernel/power/suspend.c -@@ -489,7 +489,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) - */ - int suspend_devices_and_enter(suspend_state_t state) - { -- int error; -+ int error, last_dev; - bool wakeup = false; - - if (!sleep_state_supported(state)) -@@ -508,8 +508,11 @@ int suspend_devices_and_enter(suspend_state_t state) - suspend_test_start(); - error = dpm_suspend_start(PMSG_SUSPEND); - if (error) { -+ last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1; -+ last_dev %= REC_FAILED_NUM; - pr_err("Some devices failed to suspend, or early wake event detected\n"); -- log_suspend_abort_reason("Some devices failed to suspend, or early wake event detected"); -+ log_suspend_abort_reason("%s device failed to suspend, or early wake event detected", -+ suspend_stats.failed_devs[last_dev]); - goto Recover_platform; - } - suspend_test_finish("suspend devices"); diff --git a/patches/ANDROID-Move-from-clang-r349610-to-r353983c.patch b/patches/ANDROID-Move-from-clang-r349610-to-r353983c.patch deleted file mode 100644 index 33d80b0d4f8b0223352a712c94c12583c64c1470..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Move-from-clang-r349610-to-r353983c.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Strachan -Date: Tue, 14 May 2019 16:07:58 -0700 -Subject: ANDROID: Move from clang r349610 to r353983c. - -Bug: 120439617 -Bug: 132097678 -Test: make ARCH=arm64 cuttlefish_defconfig && make ARCH=arm64 -Test: make ARCH=x86_64 x86_64_cuttlefish_defconfig && make ARCH=x86_64 -Change-Id: If5542a39e36fb4de6dd4b4135a22e188f752dd84 -Signed-off-by: Alistair Strachan ---- - build.config.gki.aarch64 | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 -index dec295284ffa..ecc2985e92cb 100644 ---- a/build.config.gki.aarch64 -+++ b/build.config.gki.aarch64 -@@ -7,7 +7,7 @@ DEFCONFIG=gki_defconfig - EXTRA_CMDS='' - KERNEL_DIR=common - POST_DEFCONFIG_CMDS="check_defconfig" --CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r349610/bin -+CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin - LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin - FILES=" - arch/arm64/boot/Image.gz diff --git a/patches/ANDROID-Remove-CONFIG_USELIB-from-x86-gki-config.patch b/patches/ANDROID-Remove-CONFIG_USELIB-from-x86-gki-config.patch deleted file mode 100644 index f5a6d06ae0ff0bb8c4ad322308d1b461c14f7b6d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Remove-CONFIG_USELIB-from-x86-gki-config.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Fri, 20 Sep 2019 15:28:37 -0700 -Subject: ANDROID: Remove CONFIG_USELIB from x86 gki config - -Bug: 138199351 -Change-Id: Ib517ad710337a38602bf7f30ecf616d6d02ca8af -Signed-off-by: Ram Muthiah ---- - arch/x86/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index bcd12981dff4..642729662b04 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -1,4 +1,5 @@ - CONFIG_LOCALVERSION="-mainline" -+# CONFIG_USELIB is not set - CONFIG_AUDIT=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y diff --git a/patches/ANDROID-Removed-check-for-asm-goto.patch b/patches/ANDROID-Removed-check-for-asm-goto.patch deleted file mode 100644 index 33f041226551842f456266da1a98057c8df4fbc6..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Removed-check-for-asm-goto.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Strachan -Date: Wed, 24 Oct 2018 13:58:11 -0700 -Subject: ANDROID: Removed check for asm-goto - -Cherry pick was manually applied due to conflicts with -upstream commits: e9666d10a56 and 829fe4aa9ac --------- -Revert "x86: Force asm-goto" - -This reverts commit e501ce957a786ecd076ea0cfb10b114e6e4d0f40. - -This change broke building the x86_64 kernel with clang. The kernel -still builds and works fine without asm-goto support. Revert this -change to unblock testing clang kernels on cuttlefish. - -Bug: 118142806 -Bug: 120440614 -Bug: 132629930 -Change-Id: Ib32498acc0596264f8cd15de0b603579dd643dd7 -Signed-off-by: Alistair Strachan -Signed-off-by: Ram Muthiah ---- - arch/x86/Makefile | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/arch/x86/Makefile b/arch/x86/Makefile -index 94df0868804b..408bb5532d1b 100644 ---- a/arch/x86/Makefile -+++ b/arch/x86/Makefile -@@ -298,10 +298,6 @@ vdso_install: - - archprepare: checkbin - checkbin: --ifndef CONFIG_CC_HAS_ASM_GOTO -- @echo Compiler lacks asm-goto support. -- @exit 1 --endif - ifdef CONFIG_RETPOLINE - ifeq ($(RETPOLINE_CFLAGS),) - @echo "You are building kernel with non-retpoline compiler." >&2 diff --git a/patches/ANDROID-Removed-extraneous-configs-from-gki.patch b/patches/ANDROID-Removed-extraneous-configs-from-gki.patch deleted file mode 100644 index 2f8ab3df4b79798e9d94d0a8a77020ac06ec5cb3..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Removed-extraneous-configs-from-gki.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Wed, 12 Jun 2019 18:05:43 -0700 -Subject: ANDROID: Removed extraneous configs from gki - -Removed SCSI_VIRTIO and VIRTIO_BALLOON - -Test: Boot x86 cuttlefish and gki -Signed-off-by: Ram Muthiah -Change-Id: I342ee9a9a2c715565ce5304f37d40575c234efd6 ---- - arch/arm64/configs/gki_defconfig | 2 -- - arch/x86/configs/gki_defconfig | 2 -- - 2 files changed, 4 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 9bc2782661dc..7eeafbecf1b9 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -196,7 +196,6 @@ CONFIG_SCSI=y - CONFIG_BLK_DEV_SD=y - CONFIG_SCSI_UFSHCD=y - CONFIG_SCSI_UFSHCD_PLATFORM=y --CONFIG_SCSI_VIRTIO=y - CONFIG_MD=y - CONFIG_BLK_DEV_DM=y - CONFIG_DM_CRYPT=y -@@ -327,7 +326,6 @@ CONFIG_RTC_DRV_PL030=y - CONFIG_RTC_DRV_PL031=y - CONFIG_VIRTIO_PCI=y - # CONFIG_VIRTIO_PCI_LEGACY is not set --CONFIG_VIRTIO_BALLOON=y - CONFIG_VIRTIO_INPUT=y - CONFIG_VIRTIO_MMIO=y - CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 7f4edee2b52d..c0993920b94d 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -174,7 +174,6 @@ CONFIG_UID_SYS_STATS=y - CONFIG_SCSI=y - # CONFIG_SCSI_PROC_FS is not set - CONFIG_BLK_DEV_SD=y --CONFIG_SCSI_VIRTIO=y - CONFIG_MD=y - CONFIG_BLK_DEV_DM=y - CONFIG_DM_CRYPT=y -@@ -282,7 +281,6 @@ CONFIG_LEDS_TRIGGERS=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_SYSTOHC is not set - CONFIG_VIRTIO_PCI=y --CONFIG_VIRTIO_BALLOON=y - CONFIG_VIRTIO_INPUT=y - CONFIG_VIRTIO_MMIO=y - CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y diff --git a/patches/ANDROID-Removed-extraneous-serial-8250-configs.patch b/patches/ANDROID-Removed-extraneous-serial-8250-configs.patch deleted file mode 100644 index 86baa08485a16b1633aee3e20776da51c2433b5e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Removed-extraneous-serial-8250-configs.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Sun, 15 Sep 2019 23:24:48 -0700 -Subject: ANDROID: Removed extraneous serial 8250 configs - -Signed-off-by: Ram Muthiah -Test: Local Boot of cuttlefish with this kernel -Bug: 132629930 -Change-Id: I12afb2b95105bfdbaa81cc51367664fa36a4f60c ---- - arch/arm64/configs/gki_defconfig | 4 ---- - arch/x86/configs/gki_defconfig | 4 ---- - 2 files changed, 8 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index d650f7d141e7..ea9960028cfd 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -264,10 +264,6 @@ CONFIG_SERIAL_8250=y - # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set - CONFIG_SERIAL_8250_CONSOLE=y - # CONFIG_SERIAL_8250_EXAR is not set --CONFIG_SERIAL_8250_NR_UARTS=48 --CONFIG_SERIAL_8250_EXTENDED=y --CONFIG_SERIAL_8250_MANY_PORTS=y --CONFIG_SERIAL_8250_SHARE_IRQ=y - CONFIG_SERIAL_OF_PLATFORM=m - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 511a763add37..a5953d43d480 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -237,10 +237,6 @@ CONFIG_INPUT_UINPUT=y - CONFIG_SERIAL_8250=y - # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set - CONFIG_SERIAL_8250_CONSOLE=y --CONFIG_SERIAL_8250_NR_UARTS=48 --CONFIG_SERIAL_8250_EXTENDED=y --CONFIG_SERIAL_8250_MANY_PORTS=y --CONFIG_SERIAL_8250_SHARE_IRQ=y - CONFIG_SERIAL_OF_PLATFORM=m - CONFIG_HW_RANDOM=y - CONFIG_HW_RANDOM_VIRTIO=m diff --git a/patches/ANDROID-Removed-hardcoded-kernel-command-line-arguments.patch b/patches/ANDROID-Removed-hardcoded-kernel-command-line-arguments.patch deleted file mode 100644 index 2af238eae67b0e47a78bd2670182b0798444786c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Removed-hardcoded-kernel-command-line-arguments.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Sun, 4 Aug 2019 13:37:09 -0700 -Subject: ANDROID: Removed hardcoded kernel command line arguments - -Test: Booted mainline on cuttlefish locally -Signed-off-by: Ram Muthiah -Change-Id: I5a32dcc1bc4faaff08b032f4ff8350adf2bbb5c1 ---- - arch/x86/configs/gki_defconfig | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 4016f8be75c5..731cec5e1bc3 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -35,8 +35,6 @@ CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y - CONFIG_SMP=y --CONFIG_CMDLINE_BOOL=y --CONFIG_CMDLINE="console=ttyS0 reboot=p" - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set diff --git a/patches/ANDROID-Removed-unnecessary-modules-from-cuttlefish.patch b/patches/ANDROID-Removed-unnecessary-modules-from-cuttlefish.patch deleted file mode 100644 index e58596ec57e48bc6bda1c3d77138d94f08bc4682..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Removed-unnecessary-modules-from-cuttlefish.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Fri, 9 Aug 2019 12:48:12 -0700 -Subject: ANDROID: Removed unnecessary modules from cuttlefish. - -Modules do not succesfuly load on cuttlefish and are not needed for gki. - -Bug: 132629930 -Test: Treehugger + Launch local KO Ramdisk -Signed-of-by: Ram Muthiah -Change-Id: I07b6c140e4c474d66132a4fb5630d18933b69e81 ---- - arch/x86/configs/gki_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 731cec5e1bc3..2d5f55d7b966 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -242,11 +242,13 @@ CONFIG_HW_RANDOM_VIRTIO=y - CONFIG_GPIOLIB=y - # CONFIG_HWMON is not set - CONFIG_DEVFREQ_THERMAL=y -+# CONFIG_X86_PKG_TEMP_THERMAL is not set - CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set - CONFIG_DRM_VIRTIO_GPU=y -+# CONFIG_LCD_CLASS_DEVICE is not set - CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_SOUND=y - CONFIG_SND=y diff --git a/patches/ANDROID-Revert-kheaders-make-headers-archive-reproducible.patch b/patches/ANDROID-Revert-kheaders-make-headers-archive-reproducible.patch deleted file mode 100644 index 48f55767efb59096745e019d8c66f7069abf88af..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Revert-kheaders-make-headers-archive-reproducible.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Delva -Date: Wed, 9 Oct 2019 15:25:35 -0400 -Subject: ANDROID: Revert "kheaders: make headers archive reproducible" - -This reverts commit 86cdd2fdc4e39c388d39c7ba2396d1a9dfd66226. - -Reason: Broke "make allmodconfig" on Android build machines - -$ tar: unrecognized option '--sort=name' -Try 'tar --help' or 'tar --usage' for more information. - -Signed-off-by: Alistair Delva -Change-Id: I3d406988f23201e5ab824ca7aed215ccc9d43279 ---- - Documentation/kbuild/reproducible-builds.rst | 13 ++++--------- - kernel/gen_kheaders.sh | 5 +---- - 2 files changed, 5 insertions(+), 13 deletions(-) - -diff --git a/Documentation/kbuild/reproducible-builds.rst b/Documentation/kbuild/reproducible-builds.rst -index 503393854e2e..ab92e98c89c8 100644 ---- a/Documentation/kbuild/reproducible-builds.rst -+++ b/Documentation/kbuild/reproducible-builds.rst -@@ -16,21 +16,16 @@ the kernel may be unreproducible, and how to avoid them. - Timestamps - ---------- - --The kernel embeds timestamps in three places: -+The kernel embeds a timestamp in two places: - - * The version string exposed by ``uname()`` and included in - ``/proc/version`` - - * File timestamps in the embedded initramfs - --* If enabled via ``CONFIG_IKHEADERS``, file timestamps of kernel -- headers embedded in the kernel or respective module, -- exposed via ``/sys/kernel/kheaders.tar.xz`` -- --By default the timestamp is the current time and in the case of --``kheaders`` the various files' modification times. This must --be overridden using the `KBUILD_BUILD_TIMESTAMP`_ variable. --If you are building from a git commit, you could use its commit date. -+By default the timestamp is the current time. This must be overridden -+using the `KBUILD_BUILD_TIMESTAMP`_ variable. If you are building -+from a git commit, you could use its commit date. - - The kernel does *not* use the ``__DATE__`` and ``__TIME__`` macros, - and enables warnings if they are used. If you incorporate external -diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh -index aff79e461fc9..9ff449888d9c 100755 ---- a/kernel/gen_kheaders.sh -+++ b/kernel/gen_kheaders.sh -@@ -71,10 +71,7 @@ done | cpio --quiet -pd $cpio_dir >/dev/null 2>&1 - find $cpio_dir -type f -print0 | - xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;' - --# Create archive and try to normalize metadata for reproducibility --tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ -- --owner=0 --group=0 --sort=name --numeric-owner \ -- -Jcf $tarfile -C $cpio_dir/ . > /dev/null -+tar -Jcf $tarfile -C $cpio_dir/ . > /dev/null - - echo "$src_files_md5" > kernel/kheaders.md5 - echo "$obj_files_md5" >> kernel/kheaders.md5 diff --git a/patches/ANDROID-Revert-um-irq-don-t-set-the-chip-for-all-irqs.patch b/patches/ANDROID-Revert-um-irq-don-t-set-the-chip-for-all-irqs.patch deleted file mode 100644 index eba9c507a49499f1b549e9b1f0feca650abf8cd4..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Revert-um-irq-don-t-set-the-chip-for-all-irqs.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Delva -Date: Thu, 22 Aug 2019 16:53:19 -0700 -Subject: ANDROID: Revert "um: irq: don't set the chip for all irqs" - -This reverts commit 1987b1b8f9f17a06255877e7917d0bb5b5377774. - -Reason: Broke UML used by kernel_tests - -Bug: 139897923 -Change-Id: If3541721fdca7cf6d77410309ae5b503b5a848d0 -Signed-off-by: Alistair Delva ---- - arch/um/kernel/irq.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c -index 3577118bb4a5..9410424af710 100644 ---- a/arch/um/kernel/irq.c -+++ b/arch/um/kernel/irq.c -@@ -480,7 +480,7 @@ void __init init_IRQ(void) - irq_set_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq); - - -- for (i = 1; i <= LAST_IRQ; i++) -+ for (i = 1; i < NR_IRQS; i++) - irq_set_chip_and_handler(i, &normal_irq_type, handle_edge_irq); - /* Initialize EPOLL Loop */ - os_setup_epoll(); diff --git a/patches/ANDROID-Revert-um-remove-uses-of-variable-length-arrays.patch b/patches/ANDROID-Revert-um-remove-uses-of-variable-length-arrays.patch deleted file mode 100644 index fa51a69e28fb331bcb8c11d246a3bd25e9b6e580..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Revert-um-remove-uses-of-variable-length-arrays.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Delva -Date: Thu, 22 Aug 2019 16:53:55 -0700 -Subject: ANDROID: Revert "um: remove uses of variable length arrays" - -This reverts commit 0d4e5ac7e78035950d564e65c38ce148cb9af681. - -Reason: Broke UML used by kernel_tests - -Bug: 139897923 -Change-Id: Ibf57c1f535e60caaef32dd14c4abbe253d8e185d -Signed-off-by: Alistair Delva ---- - arch/um/os-Linux/umid.c | 36 +++++++++--------------------------- - 1 file changed, 9 insertions(+), 27 deletions(-) - -diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c -index 44def53a11cd..4c19df8d2e80 100644 ---- a/arch/um/os-Linux/umid.c -+++ b/arch/um/os-Linux/umid.c -@@ -135,18 +135,12 @@ static int remove_files_and_dir(char *dir) - */ - static inline int is_umdir_used(char *dir) - { -- char pid[sizeof("nnnnn\0")], *end, *file; -+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; -+ char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p, n, err; -- size_t filelen; - -- err = asprintf(&file, "%s/pid", dir); -- if (err < 0) -- return 0; -- -- filelen = strlen(file); -- -- n = snprintf(file, filelen, "%s/pid", dir); -- if (n >= filelen) { -+ n = snprintf(file, sizeof(file), "%s/pid", dir); -+ if (n >= sizeof(file)) { - printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n"); - err = -E2BIG; - goto out; -@@ -191,7 +185,6 @@ static inline int is_umdir_used(char *dir) - out_close: - close(fd); - out: -- free(file); - return 0; - } - -@@ -217,21 +210,18 @@ static int umdir_take_if_dead(char *dir) - - static void __init create_pid_file(void) - { -- char pid[sizeof("nnnnn\0")], *file; -+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; -+ char pid[sizeof("nnnnn\0")]; - int fd, n; - -- file = malloc(strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")); -- if (!file) -- return; -- - if (umid_file_name("pid", file, sizeof(file))) -- goto out; -+ return; - - fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); - if (fd < 0) { - printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: " - "%s\n", file, strerror(errno)); -- goto out; -+ return; - } - - snprintf(pid, sizeof(pid), "%d\n", getpid()); -@@ -241,8 +231,6 @@ static void __init create_pid_file(void) - errno); - - close(fd); --out: -- free(file); - } - - int __init set_umid(char *name) -@@ -397,19 +385,13 @@ __uml_setup("uml_dir=", set_uml_dir, - - static void remove_umid_dir(void) - { -- char *dir, err; -- -- dir = malloc(strlen(uml_dir) + UMID_LEN + 1); -- if (!dir) -- return; -+ char dir[strlen(uml_dir) + UMID_LEN + 1], err; - - sprintf(dir, "%s%s", uml_dir, umid); - err = remove_files_and_dir(dir); - if (err) - os_warn("%s - remove_files_and_dir failed with err = %d\n", - __func__, err); -- -- free(dir); - } - - __uml_exitcall(remove_umid_dir); diff --git a/patches/ANDROID-Revert-x86-mm-Identify-the-end-of-the-kernel-area-to-be-reserved.patch b/patches/ANDROID-Revert-x86-mm-Identify-the-end-of-the-kernel-area-to-be-reserved.patch deleted file mode 100644 index a544d46251d750aba8667c44137541018e1e6a7c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-Revert-x86-mm-Identify-the-end-of-the-kernel-area-to-be-reserved.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Greg Kroah-Hartman -Date: Tue, 23 Jul 2019 14:52:18 +0200 -Subject: ANDROID: Revert "x86/mm: Identify the end of the kernel area to be - reserved" - -This reverts commit c603a309cc75f3dd018ddb20ee44c05047918cbf. - -It breaks the build with clang. - -Signed-off-by: Greg Kroah-Hartman -Change-Id: I2e50915dacfa823c80067f38dc43ef368c24bd2e ---- - arch/x86/include/asm/sections.h | 2 -- - arch/x86/kernel/setup.c | 8 +------- - arch/x86/kernel/vmlinux.lds.S | 9 +-------- - 3 files changed, 2 insertions(+), 17 deletions(-) - -diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h -index 71b32f2570ab..8ea1cfdbeabc 100644 ---- a/arch/x86/include/asm/sections.h -+++ b/arch/x86/include/asm/sections.h -@@ -13,6 +13,4 @@ extern char __end_rodata_aligned[]; - extern char __end_rodata_hpage_align[]; - #endif - --extern char __end_of_kernel_reserve[]; -- - #endif /* _ASM_X86_SECTIONS_H */ -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 77ea96b794bd..f007d910a6e6 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -836,14 +836,8 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) - - void __init setup_arch(char **cmdline_p) - { -- /* -- * Reserve the memory occupied by the kernel between _text and -- * __end_of_kernel_reserve symbols. Any kernel sections after the -- * __end_of_kernel_reserve symbol must be explicitly reserved with a -- * separate memblock_reserve() or they will be discarded. -- */ - memblock_reserve(__pa_symbol(_text), -- (unsigned long)__end_of_kernel_reserve - (unsigned long)_text); -+ (unsigned long)__bss_stop - (unsigned long)_text); - - /* - * Make sure page 0 is always reserved because on systems with -diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S -index e2feacf921a0..4f062d33ef73 100644 ---- a/arch/x86/kernel/vmlinux.lds.S -+++ b/arch/x86/kernel/vmlinux.lds.S -@@ -368,14 +368,6 @@ SECTIONS - __bss_stop = .; - } - -- /* -- * The memory occupied from _text to here, __end_of_kernel_reserve, is -- * automatically reserved in setup_arch(). Anything after here must be -- * explicitly reserved using memblock_reserve() or it will be discarded -- * and treated as available memory. -- */ -- __end_of_kernel_reserve = .; -- - . = ALIGN(PAGE_SIZE); - .brk : AT(ADDR(.brk) - LOAD_OFFSET) { - __brk_base = .; -@@ -415,6 +407,7 @@ SECTIONS - STABS_DEBUG - DWARF_DEBUG - -+ /* Sections to be discarded */ - DISCARDS - /DISCARD/ : { - *(.eh_frame) diff --git a/patches/ANDROID-add-extra-free-kbytes-tunable.patch b/patches/ANDROID-add-extra-free-kbytes-tunable.patch deleted file mode 100644 index f8a6e6a1b21785ef4f3a4a0b6c7ffddba83b757b..0000000000000000000000000000000000000000 --- a/patches/ANDROID-add-extra-free-kbytes-tunable.patch +++ /dev/null @@ -1,178 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Rik van Riel -Date: Thu, 1 Sep 2011 15:26:50 -0400 -Subject: ANDROID: add extra free kbytes tunable - -Add a userspace visible knob to tell the VM to keep an extra amount -of memory free, by increasing the gap between each zone's min and -low watermarks. - -This is useful for realtime applications that call system -calls and have a bound on the number of allocations that happen -in any short time period. In this application, extra_free_kbytes -would be left at an amount equal to or larger than than the -maximum number of allocations that happen in any burst. - -It may also be useful to reduce the memory use of virtual -machines (temporarily?), in a way that does not cause memory -fragmentation like ballooning does. - -[ccross] -Revived for use on old kernels where no other solution exists. -The tunable will be removed on kernels that do better at avoiding -direct reclaim. - -[surenb] -Will be reverted as soon as Android framework is reworked to -use upstream-supported watermark_scale_factor instead of -extra_free_kbytes. - -Bug: 86445363 -Bug: 109664768 -Bug: 120445732 -Change-Id: I765a42be8e964bfd3e2886d1ca85a29d60c3bb3e -Signed-off-by: Rik van Riel -Signed-off-by: Colin Cross -Signed-off-by: Suren Baghdasaryan ---- - Documentation/admin-guide/sysctl/vm.rst | 16 ++++++++++++++++ - kernel/sysctl.c | 9 +++++++++ - mm/page_alloc.c | 25 +++++++++++++++++++++---- - 3 files changed, 46 insertions(+), 4 deletions(-) - -diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst -index 64aeee1009ca..9e8470008227 100644 ---- a/Documentation/admin-guide/sysctl/vm.rst -+++ b/Documentation/admin-guide/sysctl/vm.rst -@@ -37,6 +37,7 @@ Currently, these files are in /proc/sys/vm: - - dirty_writeback_centisecs - - drop_caches - - extfrag_threshold -+- extra_free_kbytes - - hugetlb_shm_group - - laptop_mode - - legacy_va_layout -@@ -287,6 +288,21 @@ only use the low memory and they can fill it up with dirty data without - any throttling. - - -+extra_free_kbytes -+ -+This parameter tells the VM to keep extra free memory between the threshold -+where background reclaim (kswapd) kicks in, and the threshold where direct -+reclaim (by allocating processes) kicks in. -+ -+This is useful for workloads that require low latency memory allocations -+and have a bounded burstiness in memory allocations, for example a -+realtime application that receives and transmits network traffic -+(causing in-kernel memory allocations) with a maximum total message burst -+size of 200MB may need 200MB of extra free memory to avoid direct reclaim -+related latencies. -+ -+============================================================== -+ - hugetlb_shm_group - ================= - -diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 00fcea236eba..570cf6083712 100644 ---- a/kernel/sysctl.c -+++ b/kernel/sysctl.c -@@ -111,6 +111,7 @@ extern char core_pattern[]; - extern unsigned int core_pipe_limit; - #endif - extern int pid_max; -+extern int extra_free_kbytes; - extern int pid_max_min, pid_max_max; - extern int percpu_pagelist_fraction; - extern int latencytop_enabled; -@@ -1524,6 +1525,14 @@ static struct ctl_table vm_table[] = { - .extra1 = SYSCTL_ONE, - .extra2 = &one_thousand, - }, -+ { -+ .procname = "extra_free_kbytes", -+ .data = &extra_free_kbytes, -+ .maxlen = sizeof(extra_free_kbytes), -+ .mode = 0644, -+ .proc_handler = min_free_kbytes_sysctl_handler, -+ .extra1 = SYSCTL_ZERO, -+ }, - { - .procname = "percpu_pagelist_fraction", - .data = &percpu_pagelist_fraction, -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index c0b2e0306720..ca7e48d00f3f 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -313,6 +313,11 @@ compound_page_dtor * const compound_page_dtors[] = { - #endif - }; - -+/* -+ * Try to keep at least this much lowmem free. Do not allow normal -+ * allocations below this point, only high priority ones. Automatically -+ * tuned according to the amount of memory in the system. -+ */ - int min_free_kbytes = 1024; - int user_min_free_kbytes = -1; - #ifdef CONFIG_DISCONTIGMEM -@@ -331,6 +336,13 @@ int watermark_boost_factor __read_mostly = 15000; - #endif - int watermark_scale_factor = 10; - -+/* -+ * Extra memory for the system to try freeing. Used to temporarily -+ * free memory, to make space for new workloads. Anyone can allocate -+ * down to the min watermarks controlled by min_free_kbytes above. -+ */ -+int extra_free_kbytes = 0; -+ - static unsigned long nr_kernel_pages __initdata; - static unsigned long nr_all_pages __initdata; - static unsigned long dma_reserve __initdata; -@@ -7731,6 +7743,7 @@ static void setup_per_zone_lowmem_reserve(void) - static void __setup_per_zone_wmarks(void) - { - unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10); -+ unsigned long pages_low = extra_free_kbytes >> (PAGE_SHIFT - 10); - unsigned long lowmem_pages = 0; - struct zone *zone; - unsigned long flags; -@@ -7742,11 +7755,13 @@ static void __setup_per_zone_wmarks(void) - } - - for_each_zone(zone) { -- u64 tmp; -+ u64 tmp, low; - - spin_lock_irqsave(&zone->lock, flags); - tmp = (u64)pages_min * zone_managed_pages(zone); - do_div(tmp, lowmem_pages); -+ low = (u64)pages_low * zone_managed_pages(zone); -+ do_div(low, vm_total_pages); - if (is_highmem(zone)) { - /* - * __GFP_HIGH and PF_MEMALLOC allocations usually don't -@@ -7779,8 +7794,10 @@ static void __setup_per_zone_wmarks(void) - mult_frac(zone_managed_pages(zone), - watermark_scale_factor, 10000)); - -- zone->_watermark[WMARK_LOW] = min_wmark_pages(zone) + tmp; -- zone->_watermark[WMARK_HIGH] = min_wmark_pages(zone) + tmp * 2; -+ zone->_watermark[WMARK_LOW] = min_wmark_pages(zone) + -+ low + tmp; -+ zone->_watermark[WMARK_HIGH] = min_wmark_pages(zone) + -+ low + tmp * 2; - zone->watermark_boost = 0; - - spin_unlock_irqrestore(&zone->lock, flags); -@@ -7864,7 +7881,7 @@ core_initcall(init_per_zone_wmark_min) - /* - * min_free_kbytes_sysctl_handler - just a wrapper around proc_dointvec() so - * that we can call two helper functions whenever min_free_kbytes -- * changes. -+ * or extra_free_kbytes changes. - */ - int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write, - void __user *buffer, size_t *length, loff_t *ppos) diff --git a/patches/ANDROID-added-configs-so-that-GKI-boots-on-x86-cuttlefish.patch b/patches/ANDROID-added-configs-so-that-GKI-boots-on-x86-cuttlefish.patch deleted file mode 100644 index 00cc791dffb364badc65baa8cba5752745fa2960..0000000000000000000000000000000000000000 --- a/patches/ANDROID-added-configs-so-that-GKI-boots-on-x86-cuttlefish.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Wed, 22 May 2019 20:11:24 -0700 -Subject: ANDROID: added configs so that GKI boots on x86 cuttlefish - -Bug: 132629930 -Test: built and ran gki on cuttlefish locally -Change-Id: I2cbfef4fd97888edaa5b6413a2459160c7117bd5 -Signed-off-by: Ram Muthiah ---- - arch/x86/configs/gki_defconfig | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 18ba312d0a60..cdaba53b7bb0 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -38,6 +38,7 @@ CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_TIMES=y - CONFIG_CPU_FREQ_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_IA32_EMULATION=y - CONFIG_KPROBES=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y -@@ -156,6 +157,7 @@ CONFIG_CFG80211=y - CONFIG_MAC80211=y - # CONFIG_MAC80211_RC_MINSTREL is not set - CONFIG_RFKILL=y -+CONFIG_PCI=y - # CONFIG_ALLOW_DEV_COREDUMP is not set - CONFIG_DEBUG_DEVRES=y - CONFIG_ZRAM=y -@@ -274,6 +276,7 @@ CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_SYSTOHC is not set -+CONFIG_VIRTIO_PCI=y - CONFIG_VIRTIO_BALLOON=y - CONFIG_VIRTIO_INPUT=y - CONFIG_VIRTIO_MMIO=y -@@ -289,6 +292,7 @@ CONFIG_EXT4_FS=y - CONFIG_EXT4_FS_SECURITY=y - CONFIG_F2FS_FS=y - CONFIG_F2FS_FS_SECURITY=y -+CONFIG_FS_ENCRYPTION=y - # CONFIG_DNOTIFY is not set - CONFIG_QUOTA=y - CONFIG_QFMT_V2=y diff --git a/patches/ANDROID-adding-usb-HCD-dummy-config-to-permit-usb-write-ops-on-init.patch b/patches/ANDROID-adding-usb-HCD-dummy-config-to-permit-usb-write-ops-on-init.patch deleted file mode 100644 index 624008ba1ffa2533fb3f47243e382ab158920179..0000000000000000000000000000000000000000 --- a/patches/ANDROID-adding-usb-HCD-dummy-config-to-permit-usb-write-ops-on-init.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Wed, 3 Jul 2019 14:31:23 -0700 -Subject: ANDROID: adding usb HCD dummy config to permit usb write ops on init - -Bug: 136021903 -Change-Id: I45ae272fd7243e290f0701a7f29722788ce0cd5a -Signed-off-by: Ram Muthiah ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index ec0566116066..7c66f40c9739 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -314,6 +314,7 @@ CONFIG_HID_MULTITOUCH=y - CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_GADGET=y -+CONFIG_USB_DUMMY_HCD=y - CONFIG_USB_CONFIGFS=y - CONFIG_USB_CONFIGFS_UEVENT=y - CONFIG_USB_CONFIGFS_F_FS=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index c0993920b94d..65c67797fb74 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -267,6 +267,7 @@ CONFIG_HID_MULTITOUCH=y - CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_GADGET=y -+CONFIG_USB_DUMMY_HCD=y - CONFIG_USB_CONFIGFS=y - CONFIG_USB_CONFIGFS_UEVENT=y - CONFIG_USB_CONFIGFS_F_FS=y diff --git a/patches/ANDROID-allmodconfig-Force-gki_defconfig-as-base.patch b/patches/ANDROID-allmodconfig-Force-gki_defconfig-as-base.patch deleted file mode 100644 index 3fbe7bd0888ae227c4ef90b70d0dca5826633111..0000000000000000000000000000000000000000 --- a/patches/ANDROID-allmodconfig-Force-gki_defconfig-as-base.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Quentin Perret -Date: Mon, 30 Sep 2019 16:23:52 +0100 -Subject: ANDROID: allmodconfig: Force gki_defconfig as base - -Allmodconfig enables as many options as it can to maximize the number of -modules it can build. While this is generally a good idea, this can also -lead to very convoluted configurations (such as CPU_BIG_ENDIAN=y on -arm64) which we don't necessarily want to support even if they break. On -the other hand, gki_defconfig already contains the set of core options -we definitely want to support, so it makes sense to use that as a base. - -Point KCONFIG_ALLMODCONFIG to the relevant gki_defconfig file in order -to ensure a minimally sensible config that allconfig is not allowed to -modify. - -Bug: 140224784 -Signed-off-by: Quentin Perret -Change-Id: Ib4cf3c9565f040a577ce3cec008293520be1af84 ---- - build.config.allmodconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/build.config.allmodconfig b/build.config.allmodconfig -index 43b1a70d5800..6e0404b8de47 100644 ---- a/build.config.allmodconfig -+++ b/build.config.allmodconfig -@@ -1,4 +1,5 @@ - DEFCONFIG=allmodconfig -+KCONFIG_ALLCONFIG=${ROOT_DIR}/common/arch/${ARCH%_*}/configs/gki_defconfig - - # XFS_FS is currently broken on this branch with clang-9 - POST_DEFCONFIG_CMDS="update_config" diff --git a/patches/ANDROID-arm-enable-max-frequency-capping.patch b/patches/ANDROID-arm-enable-max-frequency-capping.patch deleted file mode 100644 index 75c127f127c242c83099dfc39f25384d51146c6d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-arm-enable-max-frequency-capping.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dietmar Eggemann -Date: Thu, 10 May 2018 16:58:04 +0100 -Subject: ANDROID: arm: enable max frequency capping - -Defines arch_scale_max_freq_capacity() to use the topology driver -scale function. - -Signed-off-by: Ionela Voinescu -Signed-off-by: Dietmar Eggemann -Signed-off-by: Quentin Perret -Change-Id: I79f444399ea3b2948364fde80ccee52a9ece5b9a ---- - arch/arm/include/asm/topology.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h -index 8a0fae94d45e..a2edacb56459 100644 ---- a/arch/arm/include/asm/topology.h -+++ b/arch/arm/include/asm/topology.h -@@ -10,6 +10,9 @@ - /* Replace task scheduler's default frequency-invariant accounting */ - #define arch_scale_freq_capacity topology_get_freq_scale - -+/* Replace task scheduler's default max-frequency-invariant accounting */ -+#define arch_scale_max_freq_capacity topology_get_max_freq_scale -+ - /* Replace task scheduler's default cpu-invariant accounting */ - #define arch_scale_cpu_capacity topology_get_cpu_scale - diff --git a/patches/ANDROID-arm64-copy-CONFIG_CMDLINE_EXTEND-from-ARM.patch b/patches/ANDROID-arm64-copy-CONFIG_CMDLINE_EXTEND-from-ARM.patch deleted file mode 100644 index bea175fb8503f62b22a8a8cc29f027220fd570ef..0000000000000000000000000000000000000000 --- a/patches/ANDROID-arm64-copy-CONFIG_CMDLINE_EXTEND-from-ARM.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Colin Cross -Date: Wed, 2 Apr 2014 18:02:15 -0700 -Subject: ANDROID: arm64: copy CONFIG_CMDLINE_EXTEND from ARM - -Copy the config choice for CONFIG_CMDLINE_EXTEND from -arch/arm/Kconfig, including CONFIG_CMDLINE_FROM_BOOTLOADER -as the default. These will be used by drivers/of/fdt.c. - -Bug: 120440972 -Change-Id: I8416038498ddf8fc1e99ab06109825eb1492aa7f -Signed-off-by: Colin Cross ---- - arch/arm64/Kconfig | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index 950a56b71ff0..acf1c5999153 100644 ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -1578,6 +1578,23 @@ config CMDLINE - entering them here. As a minimum, you should specify the the - root device (e.g. root=/dev/nfs). - -+choice -+ prompt "Kernel command line type" if CMDLINE != "" -+ default CMDLINE_FROM_BOOTLOADER -+ -+config CMDLINE_FROM_BOOTLOADER -+ bool "Use bootloader kernel arguments if available" -+ help -+ Uses the command-line options passed by the boot loader. If -+ the boot loader doesn't provide any, the default kernel command -+ string provided in CMDLINE will be used. -+ -+config CMDLINE_EXTEND -+ bool "Extend bootloader kernel arguments" -+ help -+ The command-line arguments provided by the boot loader will be -+ appended to the default kernel command string. -+ - config CMDLINE_FORCE - bool "Always use the default kernel command string" - help -@@ -1585,6 +1602,7 @@ config CMDLINE_FORCE - loader passes other arguments to the kernel. - This is useful if you cannot or don't want to change the - command-line options your boot loader passes to the kernel. -+endchoice - - config EFI_STUB - bool diff --git a/patches/ANDROID-arm64-defconfig-Enable-EAS-by-default.patch b/patches/ANDROID-arm64-defconfig-Enable-EAS-by-default.patch deleted file mode 100644 index e3beb974407b8760fcfc7c9c34189f345d0d569b..0000000000000000000000000000000000000000 --- a/patches/ANDROID-arm64-defconfig-Enable-EAS-by-default.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Quentin Perret -Date: Wed, 3 Jul 2019 10:48:14 +0100 -Subject: ANDROID: arm64: defconfig: Enable EAS by default - -Use schedutil as default cpufreq governor so EAS can start. Also, enable -util-clamp to enable frequency selection biasing. - -Change-Id: Iec9098f27c0353dabc23bd98efbca6479de41796 -Signed-off-by: Quentin Perret ---- - arch/arm64/configs/defconfig | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig -index c9a867ac32d4..7456909a8a64 100644 ---- a/arch/arm64/configs/defconfig -+++ b/arch/arm64/configs/defconfig -@@ -13,10 +13,12 @@ CONFIG_TASK_XACCT=y - CONFIG_TASK_IO_ACCOUNTING=y - CONFIG_IKCONFIG=y - CONFIG_IKCONFIG_PROC=y -+CONFIG_UCLAMP_TASK=y - CONFIG_NUMA_BALANCING=y - CONFIG_MEMCG=y - CONFIG_MEMCG_SWAP=y - CONFIG_BLK_CGROUP=y -+CONFIG_UCLAMP_TASK_GROUP=y - CONFIG_CGROUP_PIDS=y - CONFIG_CGROUP_HUGETLB=y - CONFIG_CPUSETS=y -@@ -71,10 +73,12 @@ CONFIG_COMPAT=y - CONFIG_RANDOMIZE_BASE=y - CONFIG_HIBERNATION=y - CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y -+CONFIG_ENERGY_MODEL=y - CONFIG_ARM_CPUIDLE=y - CONFIG_ARM_PSCI_CPUIDLE=y - CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_STAT=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y - CONFIG_CPU_FREQ_GOV_POWERSAVE=m - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y diff --git a/patches/ANDROID-arm64-enable-max-frequency-capping.patch b/patches/ANDROID-arm64-enable-max-frequency-capping.patch deleted file mode 100644 index a1f1d77484b535b8c272d12d723d762d1ff8089e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-arm64-enable-max-frequency-capping.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dietmar Eggemann -Date: Thu, 10 May 2018 16:54:16 +0100 -Subject: ANDROID: arm64: enable max frequency capping - -Defines arch_scale_max_freq_capacity() to use the topology driver -scale function. - -Change-Id: If7565747ec862e42ac55196240522ef8d22ca67d -Signed-off-by: Ionela Voinescu -Signed-off-by: Dietmar Eggemann -Signed-off-by: Quentin Perret ---- - arch/arm64/include/asm/topology.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h -index a4d945db95a2..70697177d6ec 100644 ---- a/arch/arm64/include/asm/topology.h -+++ b/arch/arm64/include/asm/topology.h -@@ -19,6 +19,9 @@ int pcibus_to_node(struct pci_bus *bus); - /* Replace task scheduler's default frequency-invariant accounting */ - #define arch_scale_freq_capacity topology_get_freq_scale - -+/* Replace task scheduler's default max-frequency-invariant accounting */ -+#define arch_scale_max_freq_capacity topology_get_max_freq_scale -+ - /* Replace task scheduler's default cpu-invariant accounting */ - #define arch_scale_cpu_capacity topology_get_cpu_scale - diff --git a/patches/ANDROID-binder-add-support-for-RT-prio-inheritance.patch b/patches/ANDROID-binder-add-support-for-RT-prio-inheritance.patch deleted file mode 100644 index 543ff82736751ca0c7e94eee5fd5ddbbfecc4832..0000000000000000000000000000000000000000 --- a/patches/ANDROID-binder-add-support-for-RT-prio-inheritance.patch +++ /dev/null @@ -1,570 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martijn Coenen -Date: Tue, 6 Jun 2017 17:04:42 -0700 -Subject: ANDROID: binder: add support for RT prio inheritance. - -Adds support for SCHED_BATCH/SCHED_FIFO/SCHED_RR -priority inheritance. - -Bug: 34461621 -Bug: 37293077 -Bug: 120446518 -Change-Id: I71f356e476be2933713a0ecfa2cc31aa141e2dc6 -Signed-off-by: Martijn Coenen -[AmitP: Include for struct sched_param] -Signed-off-by: Amit Pundir -[astrachan: Folded the following changes into this patch: - 69308b3b07dd ("ANDROID: binder: add min sched_policy to node.") - 7a6edeb62d86 ("ANDROID: binder: improve priority inheritance.") - 22b061b17679 ("ANDROID: binder: don't check prio permissions on restore.") - 67cf97141d81 ("ANDROID: binder: Add tracing for binder priority inheritance.") - fb92c34f7ba3 ("ANDROID: binder: add RT inheritance flag to node.") - c847b48f8cda ("ANDROID: binder: init desired_prio.sched_policy before use it")] -Signed-off-by: Alistair Strachan ---- - drivers/android/binder.c | 243 ++++++++++++++++++++++++---- - drivers/android/binder_trace.h | 24 +++ - include/uapi/linux/android/binder.h | 50 +++++- - 3 files changed, 284 insertions(+), 33 deletions(-) - -diff --git a/drivers/android/binder.c b/drivers/android/binder.c -index 5b9ac2122e89..4cd82572785d 100644 ---- a/drivers/android/binder.c -+++ b/drivers/android/binder.c -@@ -66,6 +66,7 @@ - #include - #include - -+#include - #include - #include - -@@ -296,10 +297,13 @@ struct binder_error { - * and by @lock) - * @has_async_transaction: async transaction to node in progress - * (protected by @lock) -+ * @sched_policy: minimum scheduling policy for node -+ * (invariant after initialized) - * @accept_fds: file descriptor operations supported for node - * (invariant after initialized) - * @min_priority: minimum scheduling priority - * (invariant after initialized) -+ * @inherit_rt: inherit RT scheduling policy from caller - * @txn_security_ctx: require sender's security context - * (invariant after initialized) - * @async_todo: list of async work items -@@ -337,6 +341,8 @@ struct binder_node { - /* - * invariant after initialization - */ -+ u8 sched_policy:2; -+ u8 inherit_rt:1; - u8 accept_fds:1; - u8 txn_security_ctx:1; - u8 min_priority; -@@ -410,6 +416,22 @@ enum binder_deferred_state { - BINDER_DEFERRED_RELEASE = 0x02, - }; - -+/** -+ * struct binder_priority - scheduler policy and priority -+ * @sched_policy scheduler policy -+ * @prio [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT -+ * -+ * The binder driver supports inheriting the following scheduler policies: -+ * SCHED_NORMAL -+ * SCHED_BATCH -+ * SCHED_FIFO -+ * SCHED_RR -+ */ -+struct binder_priority { -+ unsigned int sched_policy; -+ int prio; -+}; -+ - /** - * struct binder_proc - binder process bookkeeping - * @proc_node: element for binder_procs list -@@ -484,7 +506,7 @@ struct binder_proc { - int requested_threads; - int requested_threads_started; - int tmp_ref; -- long default_priority; -+ struct binder_priority default_priority; - struct dentry *debugfs_entry; - struct binder_alloc alloc; - struct binder_context *context; -@@ -535,6 +557,7 @@ enum { - * @is_dead: thread is dead and awaiting free - * when outstanding transactions are cleaned up - * (protected by @proc->inner_lock) -+ * @task: struct task_struct for this thread - * - * Bookkeeping structure for binder threads. - */ -@@ -554,6 +577,7 @@ struct binder_thread { - struct binder_stats stats; - atomic_t tmp_ref; - bool is_dead; -+ struct task_struct *task; - }; - - /** -@@ -587,8 +611,9 @@ struct binder_transaction { - struct binder_buffer *buffer; - unsigned int code; - unsigned int flags; -- long priority; -- long saved_priority; -+ struct binder_priority priority; -+ struct binder_priority saved_priority; -+ bool set_priority_called; - kuid_t sender_euid; - struct list_head fd_fixups; - binder_uintptr_t security_ctx; -@@ -1047,22 +1072,145 @@ static void binder_wakeup_proc_ilocked(struct binder_proc *proc) - binder_wakeup_thread_ilocked(proc, thread, /* sync = */false); - } - --static void binder_set_nice(long nice) -+static bool is_rt_policy(int policy) -+{ -+ return policy == SCHED_FIFO || policy == SCHED_RR; -+} -+ -+static bool is_fair_policy(int policy) -+{ -+ return policy == SCHED_NORMAL || policy == SCHED_BATCH; -+} -+ -+static bool binder_supported_policy(int policy) -+{ -+ return is_fair_policy(policy) || is_rt_policy(policy); -+} -+ -+static int to_userspace_prio(int policy, int kernel_priority) -+{ -+ if (is_fair_policy(policy)) -+ return PRIO_TO_NICE(kernel_priority); -+ else -+ return MAX_USER_RT_PRIO - 1 - kernel_priority; -+} -+ -+static int to_kernel_prio(int policy, int user_priority) - { -- long min_nice; -+ if (is_fair_policy(policy)) -+ return NICE_TO_PRIO(user_priority); -+ else -+ return MAX_USER_RT_PRIO - 1 - user_priority; -+} - -- if (can_nice(current, nice)) { -- set_user_nice(current, nice); -+static void binder_do_set_priority(struct task_struct *task, -+ struct binder_priority desired, -+ bool verify) -+{ -+ int priority; /* user-space prio value */ -+ bool has_cap_nice; -+ unsigned int policy = desired.sched_policy; -+ -+ if (task->policy == policy && task->normal_prio == desired.prio) - return; -+ -+ has_cap_nice = has_capability_noaudit(task, CAP_SYS_NICE); -+ -+ priority = to_userspace_prio(policy, desired.prio); -+ -+ if (verify && is_rt_policy(policy) && !has_cap_nice) { -+ long max_rtprio = task_rlimit(task, RLIMIT_RTPRIO); -+ -+ if (max_rtprio == 0) { -+ policy = SCHED_NORMAL; -+ priority = MIN_NICE; -+ } else if (priority > max_rtprio) { -+ priority = max_rtprio; -+ } -+ } -+ -+ if (verify && is_fair_policy(policy) && !has_cap_nice) { -+ long min_nice = rlimit_to_nice(task_rlimit(task, RLIMIT_NICE)); -+ -+ if (min_nice > MAX_NICE) { -+ binder_user_error("%d RLIMIT_NICE not set\n", -+ task->pid); -+ return; -+ } else if (priority < min_nice) { -+ priority = min_nice; -+ } -+ } -+ -+ if (policy != desired.sched_policy || -+ to_kernel_prio(policy, priority) != desired.prio) -+ binder_debug(BINDER_DEBUG_PRIORITY_CAP, -+ "%d: priority %d not allowed, using %d instead\n", -+ task->pid, desired.prio, -+ to_kernel_prio(policy, priority)); -+ -+ trace_binder_set_priority(task->tgid, task->pid, task->normal_prio, -+ to_kernel_prio(policy, priority), -+ desired.prio); -+ -+ /* Set the actual priority */ -+ if (task->policy != policy || is_rt_policy(policy)) { -+ struct sched_param params; -+ -+ params.sched_priority = is_rt_policy(policy) ? priority : 0; -+ -+ sched_setscheduler_nocheck(task, -+ policy | SCHED_RESET_ON_FORK, -+ ¶ms); - } -- min_nice = rlimit_to_nice(rlimit(RLIMIT_NICE)); -- binder_debug(BINDER_DEBUG_PRIORITY_CAP, -- "%d: nice value %ld not allowed use %ld instead\n", -- current->pid, nice, min_nice); -- set_user_nice(current, min_nice); -- if (min_nice <= MAX_NICE) -+ if (is_fair_policy(policy)) -+ set_user_nice(task, priority); -+} -+ -+static void binder_set_priority(struct task_struct *task, -+ struct binder_priority desired) -+{ -+ binder_do_set_priority(task, desired, /* verify = */ true); -+} -+ -+static void binder_restore_priority(struct task_struct *task, -+ struct binder_priority desired) -+{ -+ binder_do_set_priority(task, desired, /* verify = */ false); -+} -+ -+static void binder_transaction_priority(struct task_struct *task, -+ struct binder_transaction *t, -+ struct binder_priority node_prio, -+ bool inherit_rt) -+{ -+ struct binder_priority desired_prio = t->priority; -+ -+ if (t->set_priority_called) - return; -- binder_user_error("%d RLIMIT_NICE not set\n", current->pid); -+ -+ t->set_priority_called = true; -+ t->saved_priority.sched_policy = task->policy; -+ t->saved_priority.prio = task->normal_prio; -+ -+ if (!inherit_rt && is_rt_policy(desired_prio.sched_policy)) { -+ desired_prio.prio = NICE_TO_PRIO(0); -+ desired_prio.sched_policy = SCHED_NORMAL; -+ } -+ -+ if (node_prio.prio < t->priority.prio || -+ (node_prio.prio == t->priority.prio && -+ node_prio.sched_policy == SCHED_FIFO)) { -+ /* -+ * In case the minimum priority on the node is -+ * higher (lower value), use that priority. If -+ * the priority is the same, but the node uses -+ * SCHED_FIFO, prefer SCHED_FIFO, since it can -+ * run unbounded, unlike SCHED_RR. -+ */ -+ desired_prio = node_prio; -+ } -+ -+ binder_set_priority(task, desired_prio); - } - - static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc, -@@ -1115,6 +1263,7 @@ static struct binder_node *binder_init_node_ilocked( - binder_uintptr_t ptr = fp ? fp->binder : 0; - binder_uintptr_t cookie = fp ? fp->cookie : 0; - __u32 flags = fp ? fp->flags : 0; -+ s8 priority; - - assert_spin_locked(&proc->inner_lock); - -@@ -1147,8 +1296,12 @@ static struct binder_node *binder_init_node_ilocked( - node->ptr = ptr; - node->cookie = cookie; - node->work.type = BINDER_WORK_NODE; -- node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK; -+ priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK; -+ node->sched_policy = (flags & FLAT_BINDER_FLAG_SCHED_POLICY_MASK) >> -+ FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT; -+ node->min_priority = to_kernel_prio(node->sched_policy, priority); - node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); -+ node->inherit_rt = !!(flags & FLAT_BINDER_FLAG_INHERIT_RT); - node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX); - spin_lock_init(&node->lock); - INIT_LIST_HEAD(&node->work.entry); -@@ -2759,11 +2912,15 @@ static bool binder_proc_transaction(struct binder_transaction *t, - struct binder_thread *thread) - { - struct binder_node *node = t->buffer->target_node; -+ struct binder_priority node_prio; - bool oneway = !!(t->flags & TF_ONE_WAY); - bool pending_async = false; - - BUG_ON(!node); - binder_node_lock(node); -+ node_prio.prio = node->min_priority; -+ node_prio.sched_policy = node->sched_policy; -+ - if (oneway) { - BUG_ON(thread); - if (node->has_async_transaction) { -@@ -2784,12 +2941,15 @@ static bool binder_proc_transaction(struct binder_transaction *t, - if (!thread && !pending_async) - thread = binder_select_thread_ilocked(proc); - -- if (thread) -+ if (thread) { -+ binder_transaction_priority(thread->task, t, node_prio, -+ node->inherit_rt); - binder_enqueue_thread_work_ilocked(thread, &t->work); -- else if (!pending_async) -+ } else if (!pending_async) { - binder_enqueue_work_ilocked(&t->work, &proc->todo); -- else -+ } else { - binder_enqueue_work_ilocked(&t->work, &node->async_todo); -+ } - - if (!pending_async) - binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); -@@ -2910,7 +3070,6 @@ static void binder_transaction(struct binder_proc *proc, - } - thread->transaction_stack = in_reply_to->to_parent; - binder_inner_proc_unlock(proc); -- binder_set_nice(in_reply_to->saved_priority); - target_thread = binder_get_txn_from_and_acq_inner(in_reply_to); - if (target_thread == NULL) { - /* annotation for sparse */ -@@ -3109,7 +3268,15 @@ static void binder_transaction(struct binder_proc *proc, - t->to_thread = target_thread; - t->code = tr->code; - t->flags = tr->flags; -- t->priority = task_nice(current); -+ if (!(t->flags & TF_ONE_WAY) && -+ binder_supported_policy(current->policy)) { -+ /* Inherit supported policies for synchronous transactions */ -+ t->priority.sched_policy = current->policy; -+ t->priority.prio = current->normal_prio; -+ } else { -+ /* Otherwise, fall back to the default priority */ -+ t->priority = target_proc->default_priority; -+ } - - if (target_node && target_node->txn_security_ctx) { - u32 secid; -@@ -3436,6 +3603,7 @@ static void binder_transaction(struct binder_proc *proc, - binder_enqueue_thread_work_ilocked(target_thread, &t->work); - binder_inner_proc_unlock(target_proc); - wake_up_interruptible_sync(&target_thread->wait); -+ binder_restore_priority(current, in_reply_to->saved_priority); - binder_free_transaction(in_reply_to); - } else if (!(t->flags & TF_ONE_WAY)) { - BUG_ON(t->buffer->async_transaction != 0); -@@ -3546,6 +3714,7 @@ static void binder_transaction(struct binder_proc *proc, - - BUG_ON(thread->return_error.cmd != BR_OK); - if (in_reply_to) { -+ binder_restore_priority(current, in_reply_to->saved_priority); - thread->return_error.cmd = BR_TRANSACTION_COMPLETE; - binder_enqueue_thread_work(thread, &thread->return_error.work); - binder_send_failed_reply(in_reply_to, return_error); -@@ -4212,7 +4381,7 @@ static int binder_thread_read(struct binder_proc *proc, - wait_event_interruptible(binder_user_error_wait, - binder_stop_on_user_error < 2); - } -- binder_set_nice(proc->default_priority); -+ binder_restore_priority(current, proc->default_priority); - } - - if (non_block) { -@@ -4434,16 +4603,14 @@ static int binder_thread_read(struct binder_proc *proc, - BUG_ON(t->buffer == NULL); - if (t->buffer->target_node) { - struct binder_node *target_node = t->buffer->target_node; -+ struct binder_priority node_prio; - - trd->target.ptr = target_node->ptr; - trd->cookie = target_node->cookie; -- t->saved_priority = task_nice(current); -- if (t->priority < target_node->min_priority && -- !(t->flags & TF_ONE_WAY)) -- binder_set_nice(t->priority); -- else if (!(t->flags & TF_ONE_WAY) || -- t->saved_priority > target_node->min_priority) -- binder_set_nice(target_node->min_priority); -+ node_prio.sched_policy = target_node->sched_policy; -+ node_prio.prio = target_node->min_priority; -+ binder_transaction_priority(current, t, node_prio, -+ target_node->inherit_rt); - cmd = BR_TRANSACTION; - } else { - trd->target.ptr = 0; -@@ -4655,6 +4822,8 @@ static struct binder_thread *binder_get_thread_ilocked( - binder_stats_created(BINDER_STAT_THREAD); - thread->proc = proc; - thread->pid = current->pid; -+ get_task_struct(current); -+ thread->task = current; - atomic_set(&thread->tmp_ref, 0); - init_waitqueue_head(&thread->wait); - INIT_LIST_HEAD(&thread->todo); -@@ -4705,6 +4874,7 @@ static void binder_free_thread(struct binder_thread *thread) - BUG_ON(!list_empty(&thread->todo)); - binder_stats_deleted(BINDER_STAT_THREAD); - binder_proc_dec_tmpref(thread->proc); -+ put_task_struct(thread->task); - kfree(thread); - } - -@@ -5226,7 +5396,14 @@ static int binder_open(struct inode *nodp, struct file *filp) - get_task_struct(current->group_leader); - proc->tsk = current->group_leader; - INIT_LIST_HEAD(&proc->todo); -- proc->default_priority = task_nice(current); -+ if (binder_supported_policy(current->policy)) { -+ proc->default_priority.sched_policy = current->policy; -+ proc->default_priority.prio = current->normal_prio; -+ } else { -+ proc->default_priority.sched_policy = SCHED_NORMAL; -+ proc->default_priority.prio = NICE_TO_PRIO(0); -+ } -+ - /* binderfs stashes devices in i_private */ - if (is_binderfs_device(nodp)) { - binder_dev = nodp->i_private; -@@ -5547,13 +5724,14 @@ static void print_binder_transaction_ilocked(struct seq_file *m, - spin_lock(&t->lock); - to_proc = t->to_proc; - seq_printf(m, -- "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d", -+ "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %d:%d r%d", - prefix, t->debug_id, t, - t->from ? t->from->proc->pid : 0, - t->from ? t->from->pid : 0, - to_proc ? to_proc->pid : 0, - t->to_thread ? t->to_thread->pid : 0, -- t->code, t->flags, t->priority, t->need_reply); -+ t->code, t->flags, t->priority.sched_policy, -+ t->priority.prio, t->need_reply); - spin_unlock(&t->lock); - - if (proc != to_proc) { -@@ -5671,8 +5849,9 @@ static void print_binder_node_nilocked(struct seq_file *m, - hlist_for_each_entry(ref, &node->refs, node_entry) - count++; - -- seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d", -+ seq_printf(m, " node %d: u%016llx c%016llx pri %d:%d hs %d hw %d ls %d lw %d is %d iw %d tr %d", - node->debug_id, (u64)node->ptr, (u64)node->cookie, -+ node->sched_policy, node->min_priority, - node->has_strong_ref, node->has_weak_ref, - node->local_strong_refs, node->local_weak_refs, - node->internal_strong_refs, count, node->tmp_refs); -diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h -index 6731c3cd8145..a70e23716ad0 100644 ---- a/drivers/android/binder_trace.h -+++ b/drivers/android/binder_trace.h -@@ -76,6 +76,30 @@ DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done); - DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_write_done); - DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_read_done); - -+TRACE_EVENT(binder_set_priority, -+ TP_PROTO(int proc, int thread, unsigned int old_prio, -+ unsigned int desired_prio, unsigned int new_prio), -+ TP_ARGS(proc, thread, old_prio, new_prio, desired_prio), -+ -+ TP_STRUCT__entry( -+ __field(int, proc) -+ __field(int, thread) -+ __field(unsigned int, old_prio) -+ __field(unsigned int, new_prio) -+ __field(unsigned int, desired_prio) -+ ), -+ TP_fast_assign( -+ __entry->proc = proc; -+ __entry->thread = thread; -+ __entry->old_prio = old_prio; -+ __entry->new_prio = new_prio; -+ __entry->desired_prio = desired_prio; -+ ), -+ TP_printk("proc=%d thread=%d old=%d => new=%d desired=%d", -+ __entry->proc, __entry->thread, __entry->old_prio, -+ __entry->new_prio, __entry->desired_prio) -+); -+ - TRACE_EVENT(binder_wait_for_work, - TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo), - TP_ARGS(proc_work, transaction_stack, thread_todo), -diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h -index 2832134e5397..11babae0339f 100644 ---- a/include/uapi/linux/android/binder.h -+++ b/include/uapi/linux/android/binder.h -@@ -38,10 +38,58 @@ enum { - BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE), - }; - --enum { -+/** -+ * enum flat_binder_object_shifts: shift values for flat_binder_object_flags -+ * @FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT: shift for getting scheduler policy. -+ * -+ */ -+enum flat_binder_object_shifts { -+ FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT = 9, -+}; -+ -+/** -+ * enum flat_binder_object_flags - flags for use in flat_binder_object.flags -+ */ -+enum flat_binder_object_flags { -+ /** -+ * @FLAT_BINDER_FLAG_PRIORITY_MASK: bit-mask for min scheduler priority -+ * -+ * These bits can be used to set the minimum scheduler priority -+ * at which transactions into this node should run. Valid values -+ * in these bits depend on the scheduler policy encoded in -+ * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK. -+ * -+ * For SCHED_NORMAL/SCHED_BATCH, the valid range is between [-20..19] -+ * For SCHED_FIFO/SCHED_RR, the value can run between [1..99] -+ */ - FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, -+ /** -+ * @FLAT_BINDER_FLAG_ACCEPTS_FDS: whether the node accepts fds. -+ */ - FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, - -+ /** -+ * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK: bit-mask for scheduling policy -+ * -+ * These two bits can be used to set the min scheduling policy at which -+ * transactions on this node should run. These match the UAPI -+ * scheduler policy values, eg: -+ * 00b: SCHED_NORMAL -+ * 01b: SCHED_FIFO -+ * 10b: SCHED_RR -+ * 11b: SCHED_BATCH -+ */ -+ FLAT_BINDER_FLAG_SCHED_POLICY_MASK = -+ 3U << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT, -+ -+ /** -+ * @FLAT_BINDER_FLAG_INHERIT_RT: whether the node inherits RT policy -+ * -+ * Only when set, calls into this node will inherit a real-time -+ * scheduling policy from the caller (for synchronous transactions). -+ */ -+ FLAT_BINDER_FLAG_INHERIT_RT = 0x800, -+ - /** - * @FLAT_BINDER_FLAG_TXN_SECURITY_CTX: request security contexts - * diff --git a/patches/ANDROID-build-configs-switch-prebuilt-path-location.patch b/patches/ANDROID-build-configs-switch-prebuilt-path-location.patch deleted file mode 100644 index 9eed0e98f5b4d7948fcee11667561b5acc77e1d0..0000000000000000000000000000000000000000 --- a/patches/ANDROID-build-configs-switch-prebuilt-path-location.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthias Maennich -Date: Mon, 8 Jul 2019 22:21:06 +0100 -Subject: ANDROID: build configs: switch prebuilt path location - -Move to a kernel specific prebuilt path. - -Bug: 135922132 -Change-Id: I8755f8f0154eecc86ad598be7a7811e9d8f068ed -Signed-off-by: Matthias Maennich ---- - build.config.gki.aarch64 | 2 +- - build.config.gki.x86_64 | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 -index 24dade721f96..79871cdc6d07 100644 ---- a/build.config.gki.aarch64 -+++ b/build.config.gki.aarch64 -@@ -8,7 +8,7 @@ EXTRA_CMDS='' - KERNEL_DIR=common - POST_DEFCONFIG_CMDS="check_defconfig" - CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin --BUILDTOOLS_PREBUILT_BIN=prebuilts/build-tools/path/linux-x86 -+BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 - LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin - FILES=" - arch/arm64/boot/Image.gz -diff --git a/build.config.gki.x86_64 b/build.config.gki.x86_64 -index 3ce45e962732..b5a7f4600101 100644 ---- a/build.config.gki.x86_64 -+++ b/build.config.gki.x86_64 -@@ -8,7 +8,7 @@ EXTRA_CMDS='' - KERNEL_DIR=common - POST_DEFCONFIG_CMDS="check_defconfig" - CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin --BUILDTOOLS_PREBUILT_BIN=prebuilts/build-tools/path/linux-x86 -+BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 - LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin - FILES=" - arch/x86/boot/bzImage diff --git a/patches/ANDROID-clk-add-pre-and-post-change-rate-callbacks.patch b/patches/ANDROID-clk-add-pre-and-post-change-rate-callbacks.patch deleted file mode 100644 index 9227eae53b8538c85ab9df6bf6a50164d5d1065d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-clk-add-pre-and-post-change-rate-callbacks.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Dai -Date: Mon, 19 Aug 2019 16:35:44 -0700 -Subject: ANDROID: clk: add pre and post change rate callbacks - -There are scenarios where a rate change could result in a configuration -change for both the targeted clock and its parent. - -For example, setting the rate for a clock could require both slewing its parent -PLL as well as adjusting the clock's divider values. Due to the fact that -rate change propagation always occurs from parent to child, we could exceed -the allowed operating frequencies for the clock as the parent slews to a higher -frequency before increasing the downstream divider. - -Add a pre change call back which allows the clock to adjust its divider -appropriately before any rate change has occurred from its parents to ensure -that the clock's requirements are always within safe frequencies during parent -rate changes. The symmetrical post change call back handles the scenario where -the divider adjusts to a lower value and can only be safely adjusted after the -parent rate changes. - -Change-Id: I4f8cf9df6fc256d065599de86a34cf99eae4d853 -Signed-off-by: David Dai ---- - drivers/clk/clk.c | 10 ++++++++++ - include/linux/clk-provider.h | 13 +++++++++++++ - 2 files changed, 23 insertions(+) - -diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c -index 1c677d7f7f53..020fdb8105cc 100644 ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -1980,6 +1980,13 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core, - fail_clk = core; - } - -+ if (core->ops->pre_rate_change) { -+ ret = core->ops->pre_rate_change(core->hw, core->rate, -+ core->new_rate); -+ if (ret) -+ fail_clk = core; -+ } -+ - hlist_for_each_entry(child, &core->children, child_node) { - /* Skip children who will be reparented to another clock */ - if (child->new_parent && child->new_parent != core) -@@ -2082,6 +2089,9 @@ static void clk_change_rate(struct clk_core *core) - if (core->flags & CLK_RECALC_NEW_RATES) - (void)clk_calc_new_rates(core, core->new_rate); - -+ if (core->ops->post_rate_change) -+ core->ops->post_rate_change(core->hw, old_rate, core->rate); -+ - /* - * Use safe iteration, as change_rate can actually swap parents - * for certain clock types. -diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h -index 2fdfe8061363..73e4369e8408 100644 ---- a/include/linux/clk-provider.h -+++ b/include/linux/clk-provider.h -@@ -199,6 +199,13 @@ struct clk_duty { - * directory is provided as an argument. Called with - * prepare_lock held. Returns 0 on success, -EERROR otherwise. - * -+ * @pre_rate_change: Optional callback for a clock to fulfill its rate -+ * change requirements before any rate change has occurred in -+ * its clock tree. Returns 0 on success, -EERROR otherwise. -+ * -+ * @post_rate_change: Optional callback for a clock to clean up any -+ * requirements that were needed while the clock and its tree -+ * was changing states. Returns 0 on success, -EERROR otherwise. - * - * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow - * implementations to split any work between atomic (enable) and sleepable -@@ -245,6 +252,12 @@ struct clk_ops { - struct clk_duty *duty); - void (*init)(struct clk_hw *hw); - void (*debug_init)(struct clk_hw *hw, struct dentry *dentry); -+ int (*pre_rate_change)(struct clk_hw *hw, -+ unsigned long rate, -+ unsigned long new_rate); -+ int (*post_rate_change)(struct clk_hw *hw, -+ unsigned long old_rate, -+ unsigned long rate); - }; - - /** diff --git a/patches/ANDROID-cpu-send-KOBJ_ONLINE-event-when-enabling-cpus.patch b/patches/ANDROID-cpu-send-KOBJ_ONLINE-event-when-enabling-cpus.patch deleted file mode 100644 index 4e2100e620176aa4800bd8f414a68a37513c08e1..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpu-send-KOBJ_ONLINE-event-when-enabling-cpus.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Thierry Strudel -Date: Tue, 14 Jun 2016 17:46:44 -0700 -Subject: ANDROID: cpu: send KOBJ_ONLINE event when enabling cpus - -In case some sysfs nodes needs to be labeled with a different label than -sysfs then user needs to be notified when a core is brought back online. - -Bug: 29359497 -Bug: 120444461 -Change-Id: I0395c86e01cd49c348fda8f93087d26f88557c91 -Signed-off-by: Thierry Strudel ---- - kernel/cpu.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/kernel/cpu.c b/kernel/cpu.c -index fc28e17940e0..4bc4f6cd5634 100644 ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -1276,6 +1276,7 @@ void __weak arch_enable_nonboot_cpus_end(void) - void enable_nonboot_cpus(void) - { - int cpu, error; -+ struct device *cpu_device; - - /* Allow everyone to use the CPU hotplug again */ - cpu_maps_update_begin(); -@@ -1293,6 +1294,12 @@ void enable_nonboot_cpus(void) - trace_suspend_resume(TPS("CPU_ON"), cpu, false); - if (!error) { - pr_info("CPU%d is up\n", cpu); -+ cpu_device = get_cpu_device(cpu); -+ if (!cpu_device) -+ pr_err("%s: failed to get cpu%d device\n", -+ __func__, cpu); -+ else -+ kobject_uevent(&cpu_device->kobj, KOBJ_ONLINE); - continue; - } - pr_warn("Error taking CPU%d up: %d\n", cpu, error); diff --git a/patches/ANDROID-cpufreq-Add-time_in_state-to-proc-uid-directories.patch b/patches/ANDROID-cpufreq-Add-time_in_state-to-proc-uid-directories.patch deleted file mode 100644 index 9ed234f1a48c833de5b08d33d4f7440788a1ad31..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-Add-time_in_state-to-proc-uid-directories.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Mon, 22 Jan 2018 18:28:08 -0800 -Subject: ANDROID: cpufreq: Add time_in_state to /proc/uid directories - -Add per-uid files that report the data in binary format rather than -text, to allow faster reading & parsing by userspace. - -Signed-off-by: Connor O'Brien -Bug: 72339335 -Bug: 127641090 -Test: compare values to those reported in /proc/uid_time_in_state -Change-Id: I463039ea7f17b842be4c70024fe772539fe2ce02 ---- - drivers/cpufreq/cpufreq_times.c | 49 +++++++++++++++++++++++++++++++++ - fs/proc/uid.c | 16 ++++++++++- - include/linux/cpufreq_times.h | 1 + - 3 files changed, 65 insertions(+), 1 deletion(-) - -diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c -index 15b52e1f82fc..a43eeee30e8e 100644 ---- a/drivers/cpufreq/cpufreq_times.c -+++ b/drivers/cpufreq/cpufreq_times.c -@@ -58,6 +58,19 @@ static struct cpu_freqs *all_freqs[NR_CPUS]; - - static unsigned int next_offset; - -+ -+/* Caller must hold rcu_read_lock() */ -+static struct uid_entry *find_uid_entry_rcu(uid_t uid) -+{ -+ struct uid_entry *uid_entry; -+ -+ hash_for_each_possible_rcu(uid_hash_table, uid_entry, hash, uid) { -+ if (uid_entry->uid == uid) -+ return uid_entry; -+ } -+ return NULL; -+} -+ - /* Caller must hold uid lock */ - static struct uid_entry *find_uid_entry_locked(uid_t uid) - { -@@ -127,6 +140,36 @@ static bool freq_index_invalid(unsigned int index) - return true; - } - -+static int single_uid_time_in_state_show(struct seq_file *m, void *ptr) -+{ -+ struct uid_entry *uid_entry; -+ unsigned int i; -+ u64 time; -+ uid_t uid = from_kuid_munged(current_user_ns(), *(kuid_t *)m->private); -+ -+ if (uid == overflowuid) -+ return -EINVAL; -+ -+ rcu_read_lock(); -+ -+ uid_entry = find_uid_entry_rcu(uid); -+ if (!uid_entry) { -+ rcu_read_unlock(); -+ return 0; -+ } -+ -+ for (i = 0; i < uid_entry->max_state; ++i) { -+ if (freq_index_invalid(i)) -+ continue; -+ time = nsec_to_clock_t(uid_entry->time_in_state[i]); -+ seq_write(m, &time, sizeof(time)); -+ } -+ -+ rcu_read_unlock(); -+ -+ return 0; -+} -+ - static void *uid_seq_start(struct seq_file *seq, loff_t *pos) - { - if (*pos >= HASH_SIZE(uid_hash_table)) -@@ -397,6 +440,12 @@ static int uid_time_in_state_open(struct inode *inode, struct file *file) - return seq_open(file, &uid_time_in_state_seq_ops); - } - -+int single_uid_time_in_state_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, single_uid_time_in_state_show, -+ &(inode->i_uid)); -+} -+ - static const struct file_operations uid_time_in_state_fops = { - .open = uid_time_in_state_open, - .read = seq_read, -diff --git a/fs/proc/uid.c b/fs/proc/uid.c -index ae720b93a0ed..311717ea199a 100644 ---- a/fs/proc/uid.c -+++ b/fs/proc/uid.c -@@ -2,6 +2,7 @@ - * /proc/uid support - */ - -+#include - #include - #include - #include -@@ -82,7 +83,20 @@ struct uid_entry { - .fop = FOP, \ - } - --static const struct uid_entry uid_base_stuff[] = {}; -+#ifdef CONFIG_CPU_FREQ_TIMES -+static const struct file_operations proc_uid_time_in_state_operations = { -+ .open = single_uid_time_in_state_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+#endif -+ -+static const struct uid_entry uid_base_stuff[] = { -+#ifdef CONFIG_CPU_FREQ_TIMES -+ NOD("time_in_state", 0444, NULL, &proc_uid_time_in_state_operations), -+#endif -+}; - - static const struct inode_operations proc_uid_def_inode_operations = { - .setattr = proc_setattr, -diff --git a/include/linux/cpufreq_times.h b/include/linux/cpufreq_times.h -index a03157f649a4..757bf0cb6070 100644 ---- a/include/linux/cpufreq_times.h -+++ b/include/linux/cpufreq_times.h -@@ -29,6 +29,7 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime); - void cpufreq_times_create_policy(struct cpufreq_policy *policy); - void cpufreq_times_record_transition(struct cpufreq_freqs *freq); - void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end); -+int single_uid_time_in_state_open(struct inode *inode, struct file *file); - #else - static inline void cpufreq_task_times_init(struct task_struct *p) {} - static inline void cpufreq_task_times_alloc(struct task_struct *p) {} diff --git a/patches/ANDROID-cpufreq-arch_topology-implement-max-frequency-capping.patch b/patches/ANDROID-cpufreq-arch_topology-implement-max-frequency-capping.patch deleted file mode 100644 index 0a60fd0beb4ee1e775681e23d90d8c39e01415fa..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-arch_topology-implement-max-frequency-capping.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dietmar Eggemann -Date: Thu, 10 May 2018 16:52:33 +0100 -Subject: ANDROID: cpufreq: arch_topology: implement max frequency capping - -Implements the Max Frequency Capping Engine (MFCE) getter function -topology_get_max_freq_scale() to provide the scheduler with a -maximum frequency scaling correction factor for more accurate cpu -capacity handling by being able to deal with max frequency capping. - -This scaling factor describes the influence of running a cpu with a -current maximum frequency (policy) lower than the maximum possible -frequency (cpuinfo). - -The factor is: - - policy_max_freq(cpu) << SCHED_CAPACITY_SHIFT / cpuinfo_max_freq(cpu) - -It also implements the MFCE setter function arch_set_max_freq_scale() -which is called from cpufreq_set_policy(). - -Change-Id: I59e52861ee260755ab0518fe1f7183a2e4e3d0fc -Signed-off-by: Ionela Voinescu -Signed-off-by: Dietmar Eggemann -[Trivial cherry-pick issue in cpufreq.c] -Signed-off-by: Quentin Perret ---- - drivers/base/arch_topology.c | 25 ++++++++++++++++++++++++- - drivers/cpufreq/cpufreq.c | 8 ++++++++ - include/linux/arch_topology.h | 8 ++++++++ - include/linux/cpufreq.h | 2 ++ - 4 files changed, 42 insertions(+), 1 deletion(-) - -diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c -index 1eb81f113786..c0cf9ef5c2f5 100644 ---- a/drivers/base/arch_topology.c -+++ b/drivers/base/arch_topology.c -@@ -22,6 +22,8 @@ - #include - - DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE; -+DEFINE_PER_CPU(unsigned long, max_cpu_freq); -+DEFINE_PER_CPU(unsigned long, max_freq_scale) = SCHED_CAPACITY_SCALE; - - void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, - unsigned long max_freq) -@@ -31,8 +33,29 @@ void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, - - scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq; - -- for_each_cpu(i, cpus) -+ for_each_cpu(i, cpus) { - per_cpu(freq_scale, i) = scale; -+ per_cpu(max_cpu_freq, i) = max_freq; -+ } -+} -+ -+void arch_set_max_freq_scale(struct cpumask *cpus, -+ unsigned long policy_max_freq) -+{ -+ unsigned long scale, max_freq; -+ int cpu = cpumask_first(cpus); -+ -+ if (cpu > nr_cpu_ids) -+ return; -+ -+ max_freq = per_cpu(max_cpu_freq, cpu); -+ if (!max_freq) -+ return; -+ -+ scale = (policy_max_freq << SCHED_CAPACITY_SHIFT) / max_freq; -+ -+ for_each_cpu(cpu, cpus) -+ per_cpu(max_freq_scale, cpu) = scale; - } - - DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; -diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -index f9de9dece70f..9c15d7f52e1c 100644 ---- a/drivers/cpufreq/cpufreq.c -+++ b/drivers/cpufreq/cpufreq.c -@@ -153,6 +153,12 @@ __weak void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, - } - EXPORT_SYMBOL_GPL(arch_set_freq_scale); - -+__weak void arch_set_max_freq_scale(struct cpumask *cpus, -+ unsigned long policy_max_freq) -+{ -+} -+EXPORT_SYMBOL_GPL(arch_set_max_freq_scale); -+ - /* - * This is a generic cpufreq init() routine which can be used by cpufreq - * drivers of SMP systems. It will do following: -@@ -2407,6 +2413,8 @@ int cpufreq_set_policy(struct cpufreq_policy *policy, - policy->max = new_policy->max; - trace_cpu_frequency_limits(policy); - -+ arch_set_max_freq_scale(policy->cpus, policy->max); -+ - policy->cached_target_freq = UINT_MAX; - - pr_debug("new min and max freqs are %u - %u kHz\n", -diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h -index 42f2b5126094..5402bc0e2b1e 100644 ---- a/include/linux/arch_topology.h -+++ b/include/linux/arch_topology.h -@@ -33,6 +33,14 @@ unsigned long topology_get_freq_scale(int cpu) - return per_cpu(freq_scale, cpu); - } - -+DECLARE_PER_CPU(unsigned long, max_freq_scale); -+ -+static inline -+unsigned long topology_get_max_freq_scale(struct sched_domain *sd, int cpu) -+{ -+ return per_cpu(max_freq_scale, cpu); -+} -+ - struct cpu_topology { - int thread_id; - int core_id; -diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h -index c57e88e85c41..fca45a2749d4 100644 ---- a/include/linux/cpufreq.h -+++ b/include/linux/cpufreq.h -@@ -984,6 +984,8 @@ extern unsigned int arch_freq_get_on_cpu(int cpu); - - extern void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, - unsigned long max_freq); -+extern void arch_set_max_freq_scale(struct cpumask *cpus, -+ unsigned long policy_max_freq); - - /* the following are really really optional */ - extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; diff --git a/patches/ANDROID-cpufreq-times-add-proc-uid_concurrent_-active-policy-_time.patch b/patches/ANDROID-cpufreq-times-add-proc-uid_concurrent_-active-policy-_time.patch deleted file mode 100644 index c6b01f153e626fcd12119463ddc733b7dcbe9db0..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-times-add-proc-uid_concurrent_-active-policy-_time.patch +++ /dev/null @@ -1,340 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Fri, 5 Oct 2018 19:20:54 -0700 -Subject: ANDROID: cpufreq: times: add - /proc/uid_concurrent_{active,policy}_time - -In order to model the energy used by the cpu, we need to expose cpu -time information to userspace. We can use this information to blame -uids for the energy they are using. - -This patch adds 2 files: - -/proc/uid_concurrent_active_time outputs the time each uid spent -running with 1 to num_possible_cpus online and not idle. - -For instance, if 4 cores are online and active for 50ms and the uid is -running on one of the cores, the uid should be blamed for 1/4 of the -base energy used by the cpu when 1 or more cores is active. - -/proc/uid_concurrent_policy_time outputs the time each uid spent -running on group of cpu's with the same policy with 1 to -num_related_cpus online and not idle. - -For instance, if 2 cores that are a part of the same policy are online -and active for 50ms and the uid is running on one of the cores, the -uid should be blamed for 1/2 of the energy that is used everytime one -or more cpus in the same policy is active. - -This patch is based on commit c89e69136fec ("ANDROID: cpufreq: -uid_concurrent_active_time") and commit 989212536842 ("ANDROID: -cpufreq: uid_concurrent_policy_time") in the android-msm-wahoo-4.4 -kernel by Marissa Wall. - -Bug: 111216804 -Bug: 127641090 -Test: cat files on hikey960 and confirm output is reasonable -Change-Id: I1a342361af5c04ecee58d1ab667c91c1bce42445 -Signed-off-by: Connor O'Brien ---- - .../ABI/testing/procfs-concurrent_time | 16 ++ - drivers/cpufreq/cpufreq_times.c | 190 +++++++++++++++++- - 2 files changed, 204 insertions(+), 2 deletions(-) - create mode 100644 Documentation/ABI/testing/procfs-concurrent_time - -diff --git a/Documentation/ABI/testing/procfs-concurrent_time b/Documentation/ABI/testing/procfs-concurrent_time -new file mode 100644 -index 000000000000..55b414289b40 ---- /dev/null -+++ b/Documentation/ABI/testing/procfs-concurrent_time -@@ -0,0 +1,16 @@ -+What: /proc/uid_concurrent_active_time -+Date: December 2018 -+Contact: Connor O'Brien -+Description: -+ The /proc/uid_concurrent_active_time file displays aggregated cputime -+ numbers for each uid, broken down by the total number of cores that were -+ active while the uid's task was running. -+ -+What: /proc/uid_concurrent_policy_time -+Date: December 2018 -+Contact: Connor O'Brien -+Description: -+ The /proc/uid_concurrent_policy_time file displays aggregated cputime -+ numbers for each uid, broken down based on the cpufreq policy -+ of the core used by the uid's task and the number of cores associated -+ with that policy that were active while the uid's task was running. -diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c -index a43eeee30e8e..aaded60c9a21 100644 ---- a/drivers/cpufreq/cpufreq_times.c -+++ b/drivers/cpufreq/cpufreq_times.c -@@ -32,11 +32,17 @@ static DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS); - static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */ - static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */ - -+struct concurrent_times { -+ atomic64_t active[NR_CPUS]; -+ atomic64_t policy[NR_CPUS]; -+}; -+ - struct uid_entry { - uid_t uid; - unsigned int max_state; - struct hlist_node hash; - struct rcu_head rcu; -+ struct concurrent_times *concurrent_times; - u64 time_in_state[0]; - }; - -@@ -87,6 +93,7 @@ static struct uid_entry *find_uid_entry_locked(uid_t uid) - static struct uid_entry *find_or_register_uid_locked(uid_t uid) - { - struct uid_entry *uid_entry, *temp; -+ struct concurrent_times *times; - unsigned int max_state = READ_ONCE(next_offset); - size_t alloc_size = sizeof(*uid_entry) + max_state * - sizeof(uid_entry->time_in_state[0]); -@@ -115,9 +122,15 @@ static struct uid_entry *find_or_register_uid_locked(uid_t uid) - uid_entry = kzalloc(alloc_size, GFP_ATOMIC); - if (!uid_entry) - return NULL; -+ times = kzalloc(sizeof(*times), GFP_ATOMIC); -+ if (!times) { -+ kfree(uid_entry); -+ return NULL; -+ } - - uid_entry->uid = uid; - uid_entry->max_state = max_state; -+ uid_entry->concurrent_times = times; - - hash_add_rcu(uid_hash_table, &uid_entry->hash, uid); - -@@ -232,6 +245,86 @@ static int uid_time_in_state_seq_show(struct seq_file *m, void *v) - return 0; - } - -+static int concurrent_time_seq_show(struct seq_file *m, void *v, -+ atomic64_t *(*get_times)(struct concurrent_times *)) -+{ -+ struct uid_entry *uid_entry; -+ int i, num_possible_cpus = num_possible_cpus(); -+ -+ rcu_read_lock(); -+ -+ hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { -+ atomic64_t *times = get_times(uid_entry->concurrent_times); -+ -+ seq_put_decimal_ull(m, "", (u64)uid_entry->uid); -+ seq_putc(m, ':'); -+ -+ for (i = 0; i < num_possible_cpus; ++i) { -+ u64 time = nsec_to_clock_t(atomic64_read(×[i])); -+ -+ seq_put_decimal_ull(m, " ", time); -+ } -+ seq_putc(m, '\n'); -+ } -+ -+ rcu_read_unlock(); -+ -+ return 0; -+} -+ -+static inline atomic64_t *get_active_times(struct concurrent_times *times) -+{ -+ return times->active; -+} -+ -+static int concurrent_active_time_seq_show(struct seq_file *m, void *v) -+{ -+ if (v == uid_hash_table) { -+ seq_put_decimal_ull(m, "cpus: ", num_possible_cpus()); -+ seq_putc(m, '\n'); -+ } -+ -+ return concurrent_time_seq_show(m, v, get_active_times); -+} -+ -+static inline atomic64_t *get_policy_times(struct concurrent_times *times) -+{ -+ return times->policy; -+} -+ -+static int concurrent_policy_time_seq_show(struct seq_file *m, void *v) -+{ -+ int i; -+ struct cpu_freqs *freqs, *last_freqs = NULL; -+ -+ if (v == uid_hash_table) { -+ int cnt = 0; -+ -+ for_each_possible_cpu(i) { -+ freqs = all_freqs[i]; -+ if (!freqs) -+ continue; -+ if (freqs != last_freqs) { -+ if (last_freqs) { -+ seq_put_decimal_ull(m, ": ", cnt); -+ seq_putc(m, ' '); -+ cnt = 0; -+ } -+ seq_put_decimal_ull(m, "policy", i); -+ -+ last_freqs = freqs; -+ } -+ cnt++; -+ } -+ if (last_freqs) { -+ seq_put_decimal_ull(m, ": ", cnt); -+ seq_putc(m, '\n'); -+ } -+ } -+ -+ return concurrent_time_seq_show(m, v, get_policy_times); -+} -+ - void cpufreq_task_times_init(struct task_struct *p) - { - unsigned long flags; -@@ -326,11 +419,16 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) - { - unsigned long flags; - unsigned int state; -+ unsigned int active_cpu_cnt = 0; -+ unsigned int policy_cpu_cnt = 0; -+ unsigned int policy_first_cpu; - struct uid_entry *uid_entry; - struct cpu_freqs *freqs = all_freqs[task_cpu(p)]; -+ struct cpufreq_policy *policy; - uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p)); -+ int cpu = 0; - -- if (!freqs || p->flags & PF_EXITING) -+ if (!freqs || is_idle_task(p) || p->flags & PF_EXITING) - return; - - state = freqs->offset + READ_ONCE(freqs->last_index); -@@ -346,6 +444,42 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) - if (uid_entry && state < uid_entry->max_state) - uid_entry->time_in_state[state] += cputime; - spin_unlock_irqrestore(&uid_lock, flags); -+ -+ rcu_read_lock(); -+ uid_entry = find_uid_entry_rcu(uid); -+ if (!uid_entry) { -+ rcu_read_unlock(); -+ return; -+ } -+ -+ for_each_possible_cpu(cpu) -+ if (!idle_cpu(cpu)) -+ ++active_cpu_cnt; -+ -+ atomic64_add(cputime, -+ &uid_entry->concurrent_times->active[active_cpu_cnt - 1]); -+ -+ policy = cpufreq_cpu_get(task_cpu(p)); -+ if (!policy) { -+ /* -+ * This CPU may have just come up and not have a cpufreq policy -+ * yet. -+ */ -+ rcu_read_unlock(); -+ return; -+ } -+ -+ for_each_cpu(cpu, policy->related_cpus) -+ if (!idle_cpu(cpu)) -+ ++policy_cpu_cnt; -+ -+ policy_first_cpu = cpumask_first(policy->related_cpus); -+ cpufreq_cpu_put(policy); -+ -+ atomic64_add(cputime, -+ &uid_entry->concurrent_times->policy[policy_first_cpu + -+ policy_cpu_cnt - 1]); -+ rcu_read_unlock(); - } - - void cpufreq_times_create_policy(struct cpufreq_policy *policy) -@@ -387,6 +521,14 @@ void cpufreq_times_create_policy(struct cpufreq_policy *policy) - all_freqs[cpu] = freqs; - } - -+static void uid_entry_reclaim(struct rcu_head *rcu) -+{ -+ struct uid_entry *uid_entry = container_of(rcu, struct uid_entry, rcu); -+ -+ kfree(uid_entry->concurrent_times); -+ kfree(uid_entry); -+} -+ - void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end) - { - struct uid_entry *uid_entry; -@@ -400,7 +542,7 @@ void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end) - hash, uid_start) { - if (uid_start == uid_entry->uid) { - hash_del_rcu(&uid_entry->hash); -- kfree_rcu(uid_entry, rcu); -+ call_rcu(&uid_entry->rcu, uid_entry_reclaim); - } - } - } -@@ -453,11 +595,55 @@ static const struct file_operations uid_time_in_state_fops = { - .release = seq_release, - }; - -+static const struct seq_operations concurrent_active_time_seq_ops = { -+ .start = uid_seq_start, -+ .next = uid_seq_next, -+ .stop = uid_seq_stop, -+ .show = concurrent_active_time_seq_show, -+}; -+ -+static int concurrent_active_time_open(struct inode *inode, struct file *file) -+{ -+ return seq_open(file, &concurrent_active_time_seq_ops); -+} -+ -+static const struct file_operations concurrent_active_time_fops = { -+ .open = concurrent_active_time_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release, -+}; -+ -+static const struct seq_operations concurrent_policy_time_seq_ops = { -+ .start = uid_seq_start, -+ .next = uid_seq_next, -+ .stop = uid_seq_stop, -+ .show = concurrent_policy_time_seq_show, -+}; -+ -+static int concurrent_policy_time_open(struct inode *inode, struct file *file) -+{ -+ return seq_open(file, &concurrent_policy_time_seq_ops); -+} -+ -+static const struct file_operations concurrent_policy_time_fops = { -+ .open = concurrent_policy_time_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release, -+}; -+ - static int __init cpufreq_times_init(void) - { - proc_create_data("uid_time_in_state", 0444, NULL, - &uid_time_in_state_fops, NULL); - -+ proc_create_data("uid_concurrent_active_time", 0444, NULL, -+ &concurrent_active_time_fops, NULL); -+ -+ proc_create_data("uid_concurrent_policy_time", 0444, NULL, -+ &concurrent_policy_time_fops, NULL); -+ - return 0; - } - diff --git a/patches/ANDROID-cpufreq-times-don-t-copy-invalid-freqs-from-freq-table.patch b/patches/ANDROID-cpufreq-times-don-t-copy-invalid-freqs-from-freq-table.patch deleted file mode 100644 index 8ce77cf8ca2d0a0ea6997023b3a1cbb2d97b9b35..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-times-don-t-copy-invalid-freqs-from-freq-table.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Fri, 1 Mar 2019 15:40:30 -0800 -Subject: ANDROID: cpufreq: times: don't copy invalid freqs from freq table - -Invalid frequency checks are a bottleneck in reading -/proc/uid_time_in_state, but there's no reason to include invalid -frequencies in our local copies of frequency tables. Revise -cpufreq_times_create_policy() to only copy valid frequencies, and -eliminate all the checks this change makes unnecessary. - -Bug: 111216804 -Test: cat /proc/uid_time_in_state & confirm values & format are sane -Test: /proc/uid_time_in_state read times reduced by ~40% -Change-Id: I506420a6ac5fe8a6c87d01b16ad267b192d43f1d -Signed-off-by: Connor O'Brien ---- - drivers/cpufreq/cpufreq_times.c | 55 ++++++++++++--------------------- - 1 file changed, 19 insertions(+), 36 deletions(-) - -diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c -index 2883d675b1eb..5b5248a7c87c 100644 ---- a/drivers/cpufreq/cpufreq_times.c -+++ b/drivers/cpufreq/cpufreq_times.c -@@ -137,27 +137,10 @@ static struct uid_entry *find_or_register_uid_locked(uid_t uid) - return uid_entry; - } - --static bool freq_index_invalid(unsigned int index) --{ -- unsigned int cpu; -- struct cpu_freqs *freqs; -- -- for_each_possible_cpu(cpu) { -- freqs = all_freqs[cpu]; -- if (!freqs || index < freqs->offset || -- freqs->offset + freqs->max_state <= index) -- continue; -- return freqs->freq_table[index - freqs->offset] == -- CPUFREQ_ENTRY_INVALID; -- } -- return true; --} -- - static int single_uid_time_in_state_show(struct seq_file *m, void *ptr) - { - struct uid_entry *uid_entry; - unsigned int i; -- u64 time; - uid_t uid = from_kuid_munged(current_user_ns(), *(kuid_t *)m->private); - - if (uid == overflowuid) -@@ -172,9 +155,7 @@ static int single_uid_time_in_state_show(struct seq_file *m, void *ptr) - } - - for (i = 0; i < uid_entry->max_state; ++i) { -- if (freq_index_invalid(i)) -- continue; -- time = nsec_to_clock_t(uid_entry->time_in_state[i]); -+ u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]); - seq_write(m, &time, sizeof(time)); - } - -@@ -219,9 +200,6 @@ static int uid_time_in_state_seq_show(struct seq_file *m, void *v) - continue; - last_freqs = freqs; - for (i = 0; i < freqs->max_state; i++) { -- if (freqs->freq_table[i] == -- CPUFREQ_ENTRY_INVALID) -- continue; - seq_put_decimal_ull(m, " ", - freqs->freq_table[i]); - } -@@ -237,10 +215,7 @@ static int uid_time_in_state_seq_show(struct seq_file *m, void *v) - seq_putc(m, ':'); - } - for (i = 0; i < uid_entry->max_state; ++i) { -- u64 time; -- if (freq_index_invalid(i)) -- continue; -- time = nsec_to_clock_t(uid_entry->time_in_state[i]); -+ u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]); - seq_put_decimal_ull(m, " ", time); - } - if (uid_entry->max_state) -@@ -407,8 +382,6 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, - - seq_printf(m, "cpu%u\n", cpu); - for (i = 0; i < freqs->max_state; i++) { -- if (freqs->freq_table[i] == CPUFREQ_ENTRY_INVALID) -- continue; - cputime = 0; - if (freqs->offset + i < p->max_state && - p->time_in_state) -@@ -488,9 +461,19 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) - rcu_read_unlock(); - } - -+static int cpufreq_times_get_index(struct cpu_freqs *freqs, unsigned int freq) -+{ -+ int index; -+ for (index = 0; index < freqs->max_state; ++index) { -+ if (freqs->freq_table[index] == freq) -+ return index; -+ } -+ return -1; -+} -+ - void cpufreq_times_create_policy(struct cpufreq_policy *policy) - { -- int cpu, index; -+ int cpu, index = 0; - unsigned int count = 0; - struct cpufreq_frequency_table *pos, *table; - struct cpu_freqs *freqs; -@@ -503,7 +486,7 @@ void cpufreq_times_create_policy(struct cpufreq_policy *policy) - if (!table) - return; - -- cpufreq_for_each_entry(pos, table) -+ cpufreq_for_each_valid_entry(pos, table) - count++; - - tmp = kzalloc(sizeof(*freqs) + sizeof(freqs->freq_table[0]) * count, -@@ -514,13 +497,13 @@ void cpufreq_times_create_policy(struct cpufreq_policy *policy) - freqs = tmp; - freqs->max_state = count; - -- index = cpufreq_frequency_table_get_index(policy, policy->cur); -+ cpufreq_for_each_valid_entry(pos, table) -+ freqs->freq_table[index++] = pos->frequency; -+ -+ index = cpufreq_times_get_index(freqs, policy->cur); - if (index >= 0) - WRITE_ONCE(freqs->last_index, index); - -- cpufreq_for_each_entry(pos, table) -- freqs->freq_table[pos - table] = pos->frequency; -- - freqs->offset = next_offset; - WRITE_ONCE(next_offset, freqs->offset + count); - for_each_cpu(cpu, policy->related_cpus) -@@ -564,7 +547,7 @@ void cpufreq_times_record_transition(struct cpufreq_policy *policy, - if (!freqs) - return; - -- index = cpufreq_frequency_table_get_index(policy, new_freq); -+ index = cpufreq_times_get_index(freqs, new_freq); - if (index >= 0) - WRITE_ONCE(freqs->last_index, index); - } diff --git a/patches/ANDROID-cpufreq-times-optimize-proc-files.patch b/patches/ANDROID-cpufreq-times-optimize-proc-files.patch deleted file mode 100644 index 68b9b4058102bc5ed04cc7c05ab0b89480498dc5..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-times-optimize-proc-files.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Wed, 20 Feb 2019 12:17:48 -0800 -Subject: ANDROID: cpufreq: times: optimize proc files - -The majority of the time spent reading /proc/uid_time_in_state is due -to seq_printf calls. Use the faster seq_put_* variations instead. - -Also skip empty hash buckets in uid_seq_next for a further performance -improvement. - -Bug: 111216804 -Bug: 127641090 -Test: Read /proc/uid_time_in_state and confirm output is sane -Test: Compare read times to confirm performance improvement -Change-Id: If8783b498ed73d2ddb186a49438af41ac5ab9957 -Signed-off-by: Connor O'Brien ---- - drivers/cpufreq/cpufreq_times.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - -diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c -index 42420c5e1e6f..2883d675b1eb 100644 ---- a/drivers/cpufreq/cpufreq_times.c -+++ b/drivers/cpufreq/cpufreq_times.c -@@ -193,10 +193,12 @@ static void *uid_seq_start(struct seq_file *seq, loff_t *pos) - - static void *uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) - { -- (*pos)++; -+ do { -+ (*pos)++; - -- if (*pos >= HASH_SIZE(uid_hash_table)) -- return NULL; -+ if (*pos >= HASH_SIZE(uid_hash_table)) -+ return NULL; -+ } while (hlist_empty(&uid_hash_table[*pos])); - - return &uid_hash_table[*pos]; - } -@@ -220,7 +222,8 @@ static int uid_time_in_state_seq_show(struct seq_file *m, void *v) - if (freqs->freq_table[i] == - CPUFREQ_ENTRY_INVALID) - continue; -- seq_printf(m, " %d", freqs->freq_table[i]); -+ seq_put_decimal_ull(m, " ", -+ freqs->freq_table[i]); - } - } - seq_putc(m, '\n'); -@@ -229,13 +232,16 @@ static int uid_time_in_state_seq_show(struct seq_file *m, void *v) - rcu_read_lock(); - - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { -- if (uid_entry->max_state) -- seq_printf(m, "%d:", uid_entry->uid); -+ if (uid_entry->max_state) { -+ seq_put_decimal_ull(m, "", uid_entry->uid); -+ seq_putc(m, ':'); -+ } - for (i = 0; i < uid_entry->max_state; ++i) { -+ u64 time; - if (freq_index_invalid(i)) - continue; -- seq_printf(m, " %lu", (unsigned long)nsec_to_clock_t( -- uid_entry->time_in_state[i])); -+ time = nsec_to_clock_t(uid_entry->time_in_state[i]); -+ seq_put_decimal_ull(m, " ", time); - } - if (uid_entry->max_state) - seq_putc(m, '\n'); diff --git a/patches/ANDROID-cpufreq-times-record-fast-switch-frequency-transitions.patch b/patches/ANDROID-cpufreq-times-record-fast-switch-frequency-transitions.patch deleted file mode 100644 index 2e652eb7566b904ccf5ef96b68537ba43f477e7e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-times-record-fast-switch-frequency-transitions.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Fri, 8 Feb 2019 12:30:41 -0800 -Subject: ANDROID: cpufreq: times: record fast switch frequency transitions - -cpufreq_times_record_transition() is not called when fast switch is -enabled, leading /proc/uid_time_in_state to attribute all time on a -cluster to a single frequency. To fix this, add a call to -cpufreq_times_record_transition() in the fast switch path. - -Also revise cpufreq_times_record_transition() to simplify the new call -and more closely align with cpufreq_stats_record_transition(). - -Bug: 121287027 -Bug: 127641090 -Test: /proc/uid_time_in_state shows times for more than one freq per -cluster -Change-Id: Ib63d19006878fafb88475e401ef243bdd8b11979 -Signed-off-by: Connor O'Brien ---- - drivers/cpufreq/cpufreq.c | 10 ++++++++-- - drivers/cpufreq/cpufreq_times.c | 15 ++++----------- - include/linux/cpufreq_times.h | 5 +++-- - 3 files changed, 15 insertions(+), 15 deletions(-) - -diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -index a6512ee4b8cc..f9de9dece70f 100644 ---- a/drivers/cpufreq/cpufreq.c -+++ b/drivers/cpufreq/cpufreq.c -@@ -380,7 +380,7 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy, - CPUFREQ_POSTCHANGE, freqs); - - cpufreq_stats_record_transition(policy, freqs->new); -- cpufreq_times_record_transition(freqs); -+ cpufreq_times_record_transition(policy, freqs->new); - policy->cur = freqs->new; - } - } -@@ -2023,9 +2023,15 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier); - unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, - unsigned int target_freq) - { -+ int ret; -+ - target_freq = clamp_val(target_freq, policy->min, policy->max); - -- return cpufreq_driver->fast_switch(policy, target_freq); -+ ret = cpufreq_driver->fast_switch(policy, target_freq); -+ if (ret) -+ cpufreq_times_record_transition(policy, ret); -+ -+ return ret; - } - EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch); - -diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c -index aaded60c9a21..42420c5e1e6f 100644 ---- a/drivers/cpufreq/cpufreq_times.c -+++ b/drivers/cpufreq/cpufreq_times.c -@@ -550,24 +550,17 @@ void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end) - spin_unlock_irqrestore(&uid_lock, flags); - } - --void cpufreq_times_record_transition(struct cpufreq_freqs *freq) -+void cpufreq_times_record_transition(struct cpufreq_policy *policy, -+ unsigned int new_freq) - { - int index; -- struct cpu_freqs *freqs = all_freqs[freq->cpu]; -- struct cpufreq_policy *policy; -- -+ struct cpu_freqs *freqs = all_freqs[policy->cpu]; - if (!freqs) - return; - -- policy = cpufreq_cpu_get(freq->cpu); -- if (!policy) -- return; -- -- index = cpufreq_frequency_table_get_index(policy, freq->new); -+ index = cpufreq_frequency_table_get_index(policy, new_freq); - if (index >= 0) - WRITE_ONCE(freqs->last_index, index); -- -- cpufreq_cpu_put(policy); - } - - static const struct seq_operations uid_time_in_state_seq_ops = { -diff --git a/include/linux/cpufreq_times.h b/include/linux/cpufreq_times.h -index 757bf0cb6070..0eb6dc9d0fe2 100644 ---- a/include/linux/cpufreq_times.h -+++ b/include/linux/cpufreq_times.h -@@ -27,7 +27,8 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, - struct pid *pid, struct task_struct *p); - void cpufreq_acct_update_power(struct task_struct *p, u64 cputime); - void cpufreq_times_create_policy(struct cpufreq_policy *policy); --void cpufreq_times_record_transition(struct cpufreq_freqs *freq); -+void cpufreq_times_record_transition(struct cpufreq_policy *policy, -+ unsigned int new_freq); - void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end); - int single_uid_time_in_state_open(struct inode *inode, struct file *file); - #else -@@ -38,7 +39,7 @@ static inline void cpufreq_acct_update_power(struct task_struct *p, - u64 cputime) {} - static inline void cpufreq_times_create_policy(struct cpufreq_policy *policy) {} - static inline void cpufreq_times_record_transition( -- struct cpufreq_freqs *freq) {} -+ struct cpufreq_policy *policy, unsigned int new_freq) {} - static inline void cpufreq_task_times_remove_uids(uid_t uid_start, - uid_t uid_end) {} - #endif /* CONFIG_CPU_FREQ_TIMES */ diff --git a/patches/ANDROID-cpufreq-times-track-per-uid-time-in-state.patch b/patches/ANDROID-cpufreq-times-track-per-uid-time-in-state.patch deleted file mode 100644 index a378a5dd64d964d46052411b28f76cbc2b72a5bb..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-times-track-per-uid-time-in-state.patch +++ /dev/null @@ -1,328 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Tue, 6 Feb 2018 13:30:27 -0800 -Subject: ANDROID: cpufreq: times: track per-uid time in state - -Add /proc/uid_time_in_state showing per uid/frequency/cluster -times. Allow uid removal through /proc/uid_cputime/remove_uid_range. - -Signed-off-by: Connor O'Brien -Bug: 72339335 -Bug: 127641090 -Test: Read /proc/uid_time_in_state -Change-Id: I20ba3546a27c25b7e7991e2a86986e158aafa58c ---- - drivers/cpufreq/cpufreq_times.c | 208 ++++++++++++++++++++++++++++++++ - drivers/misc/uid_sys_stats.c | 4 + - include/linux/cpufreq_times.h | 3 + - 3 files changed, 215 insertions(+) - -diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c -index 339a3e9cf082..15b52e1f82fc 100644 ---- a/drivers/cpufreq/cpufreq_times.c -+++ b/drivers/cpufreq/cpufreq_times.c -@@ -15,14 +15,30 @@ - - #include - #include -+#include -+#include - #include -+#include - #include - #include - #include - #include - #include - -+#define UID_HASH_BITS 10 -+ -+static DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS); -+ - static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */ -+static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */ -+ -+struct uid_entry { -+ uid_t uid; -+ unsigned int max_state; -+ struct hlist_node hash; -+ struct rcu_head rcu; -+ u64 time_in_state[0]; -+}; - - /** - * struct cpu_freqs - per-cpu frequency information -@@ -42,6 +58,137 @@ static struct cpu_freqs *all_freqs[NR_CPUS]; - - static unsigned int next_offset; - -+/* Caller must hold uid lock */ -+static struct uid_entry *find_uid_entry_locked(uid_t uid) -+{ -+ struct uid_entry *uid_entry; -+ -+ hash_for_each_possible(uid_hash_table, uid_entry, hash, uid) { -+ if (uid_entry->uid == uid) -+ return uid_entry; -+ } -+ return NULL; -+} -+ -+/* Caller must hold uid lock */ -+static struct uid_entry *find_or_register_uid_locked(uid_t uid) -+{ -+ struct uid_entry *uid_entry, *temp; -+ unsigned int max_state = READ_ONCE(next_offset); -+ size_t alloc_size = sizeof(*uid_entry) + max_state * -+ sizeof(uid_entry->time_in_state[0]); -+ -+ uid_entry = find_uid_entry_locked(uid); -+ if (uid_entry) { -+ if (uid_entry->max_state == max_state) -+ return uid_entry; -+ /* uid_entry->time_in_state is too small to track all freqs, so -+ * expand it. -+ */ -+ temp = __krealloc(uid_entry, alloc_size, GFP_ATOMIC); -+ if (!temp) -+ return uid_entry; -+ temp->max_state = max_state; -+ memset(temp->time_in_state + uid_entry->max_state, 0, -+ (max_state - uid_entry->max_state) * -+ sizeof(uid_entry->time_in_state[0])); -+ if (temp != uid_entry) { -+ hlist_replace_rcu(&uid_entry->hash, &temp->hash); -+ kfree_rcu(uid_entry, rcu); -+ } -+ return temp; -+ } -+ -+ uid_entry = kzalloc(alloc_size, GFP_ATOMIC); -+ if (!uid_entry) -+ return NULL; -+ -+ uid_entry->uid = uid; -+ uid_entry->max_state = max_state; -+ -+ hash_add_rcu(uid_hash_table, &uid_entry->hash, uid); -+ -+ return uid_entry; -+} -+ -+static bool freq_index_invalid(unsigned int index) -+{ -+ unsigned int cpu; -+ struct cpu_freqs *freqs; -+ -+ for_each_possible_cpu(cpu) { -+ freqs = all_freqs[cpu]; -+ if (!freqs || index < freqs->offset || -+ freqs->offset + freqs->max_state <= index) -+ continue; -+ return freqs->freq_table[index - freqs->offset] == -+ CPUFREQ_ENTRY_INVALID; -+ } -+ return true; -+} -+ -+static void *uid_seq_start(struct seq_file *seq, loff_t *pos) -+{ -+ if (*pos >= HASH_SIZE(uid_hash_table)) -+ return NULL; -+ -+ return &uid_hash_table[*pos]; -+} -+ -+static void *uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) -+{ -+ (*pos)++; -+ -+ if (*pos >= HASH_SIZE(uid_hash_table)) -+ return NULL; -+ -+ return &uid_hash_table[*pos]; -+} -+ -+static void uid_seq_stop(struct seq_file *seq, void *v) { } -+ -+static int uid_time_in_state_seq_show(struct seq_file *m, void *v) -+{ -+ struct uid_entry *uid_entry; -+ struct cpu_freqs *freqs, *last_freqs = NULL; -+ int i, cpu; -+ -+ if (v == uid_hash_table) { -+ seq_puts(m, "uid:"); -+ for_each_possible_cpu(cpu) { -+ freqs = all_freqs[cpu]; -+ if (!freqs || freqs == last_freqs) -+ continue; -+ last_freqs = freqs; -+ for (i = 0; i < freqs->max_state; i++) { -+ if (freqs->freq_table[i] == -+ CPUFREQ_ENTRY_INVALID) -+ continue; -+ seq_printf(m, " %d", freqs->freq_table[i]); -+ } -+ } -+ seq_putc(m, '\n'); -+ } -+ -+ rcu_read_lock(); -+ -+ hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { -+ if (uid_entry->max_state) -+ seq_printf(m, "%d:", uid_entry->uid); -+ for (i = 0; i < uid_entry->max_state; ++i) { -+ if (freq_index_invalid(i)) -+ continue; -+ seq_printf(m, " %lu", (unsigned long)nsec_to_clock_t( -+ uid_entry->time_in_state[i])); -+ } -+ if (uid_entry->max_state) -+ seq_putc(m, '\n'); -+ } -+ -+ rcu_read_unlock(); -+ return 0; -+} -+ - void cpufreq_task_times_init(struct task_struct *p) - { - unsigned long flags; -@@ -90,6 +237,9 @@ void cpufreq_task_times_exit(struct task_struct *p) - unsigned long flags; - void *temp; - -+ if (!p->time_in_state) -+ return; -+ - spin_lock_irqsave(&task_time_in_state_lock, flags); - temp = p->time_in_state; - p->time_in_state = NULL; -@@ -133,7 +283,9 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) - { - unsigned long flags; - unsigned int state; -+ struct uid_entry *uid_entry; - struct cpu_freqs *freqs = all_freqs[task_cpu(p)]; -+ uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p)); - - if (!freqs || p->flags & PF_EXITING) - return; -@@ -145,6 +297,12 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) - p->time_in_state) - p->time_in_state[state] += cputime; - spin_unlock_irqrestore(&task_time_in_state_lock, flags); -+ -+ spin_lock_irqsave(&uid_lock, flags); -+ uid_entry = find_or_register_uid_locked(uid); -+ if (uid_entry && state < uid_entry->max_state) -+ uid_entry->time_in_state[state] += cputime; -+ spin_unlock_irqrestore(&uid_lock, flags); - } - - void cpufreq_times_create_policy(struct cpufreq_policy *policy) -@@ -186,6 +344,27 @@ void cpufreq_times_create_policy(struct cpufreq_policy *policy) - all_freqs[cpu] = freqs; - } - -+void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end) -+{ -+ struct uid_entry *uid_entry; -+ struct hlist_node *tmp; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&uid_lock, flags); -+ -+ for (; uid_start <= uid_end; uid_start++) { -+ hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp, -+ hash, uid_start) { -+ if (uid_start == uid_entry->uid) { -+ hash_del_rcu(&uid_entry->hash); -+ kfree_rcu(uid_entry, rcu); -+ } -+ } -+ } -+ -+ spin_unlock_irqrestore(&uid_lock, flags); -+} -+ - void cpufreq_times_record_transition(struct cpufreq_freqs *freq) - { - int index; -@@ -205,3 +384,32 @@ void cpufreq_times_record_transition(struct cpufreq_freqs *freq) - - cpufreq_cpu_put(policy); - } -+ -+static const struct seq_operations uid_time_in_state_seq_ops = { -+ .start = uid_seq_start, -+ .next = uid_seq_next, -+ .stop = uid_seq_stop, -+ .show = uid_time_in_state_seq_show, -+}; -+ -+static int uid_time_in_state_open(struct inode *inode, struct file *file) -+{ -+ return seq_open(file, &uid_time_in_state_seq_ops); -+} -+ -+static const struct file_operations uid_time_in_state_fops = { -+ .open = uid_time_in_state_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release, -+}; -+ -+static int __init cpufreq_times_init(void) -+{ -+ proc_create_data("uid_time_in_state", 0444, NULL, -+ &uid_time_in_state_fops, NULL); -+ -+ return 0; -+} -+ -+early_initcall(cpufreq_times_init); -diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c -index 36b5f37fca2f..88dc1cd3a204 100644 ---- a/drivers/misc/uid_sys_stats.c -+++ b/drivers/misc/uid_sys_stats.c -@@ -14,6 +14,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -420,6 +421,9 @@ static ssize_t uid_remove_write(struct file *file, - return -EINVAL; - } - -+ /* Also remove uids from /proc/uid_time_in_state */ -+ cpufreq_task_times_remove_uids(uid_start, uid_end); -+ - rt_mutex_lock(&uid_lock); - - for (; uid_start <= uid_end; uid_start++) { -diff --git a/include/linux/cpufreq_times.h b/include/linux/cpufreq_times.h -index bfef6e62c68a..a03157f649a4 100644 ---- a/include/linux/cpufreq_times.h -+++ b/include/linux/cpufreq_times.h -@@ -28,6 +28,7 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, - void cpufreq_acct_update_power(struct task_struct *p, u64 cputime); - void cpufreq_times_create_policy(struct cpufreq_policy *policy); - void cpufreq_times_record_transition(struct cpufreq_freqs *freq); -+void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end); - #else - static inline void cpufreq_task_times_init(struct task_struct *p) {} - static inline void cpufreq_task_times_alloc(struct task_struct *p) {} -@@ -37,5 +38,7 @@ static inline void cpufreq_acct_update_power(struct task_struct *p, - static inline void cpufreq_times_create_policy(struct cpufreq_policy *policy) {} - static inline void cpufreq_times_record_transition( - struct cpufreq_freqs *freq) {} -+static inline void cpufreq_task_times_remove_uids(uid_t uid_start, -+ uid_t uid_end) {} - #endif /* CONFIG_CPU_FREQ_TIMES */ - #endif /* _LINUX_CPUFREQ_TIMES_H */ diff --git a/patches/ANDROID-cpufreq-track-per-task-time-in-state.patch b/patches/ANDROID-cpufreq-track-per-task-time-in-state.patch deleted file mode 100644 index 0caca72adcd4f9c0f5d8089c23726f50873f2ed1..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cpufreq-track-per-task-time-in-state.patch +++ /dev/null @@ -1,473 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Wed, 31 Jan 2018 18:11:57 -0800 -Subject: ANDROID: cpufreq: track per-task time in state - -Add time in state data to task structs, and create -/proc//time_in_state files to show how long each individual task -has run at each frequency. -Create a CONFIG_CPU_FREQ_TIMES option to enable/disable this tracking. - -Bug: 72339335 -Bug: 127641090 -Test: Read /proc//time_in_state -Change-Id: Ia6456754f4cb1e83b2bc35efa8fbe9f8696febc8 -Signed-off-by: Connor O'Brien -[astrachan: Folded the following changes into this patch: - a6d3de6a7fba ("ANDROID: Reduce use of #ifdef CONFIG_CPU_FREQ_TIMES") - b89ada5d9c09 ("ANDROID: Fix massive cpufreq_times memory leaks")] -Signed-off-by: Alistair Strachan ---- - drivers/cpufreq/Kconfig | 7 ++ - drivers/cpufreq/Makefile | 5 +- - drivers/cpufreq/cpufreq.c | 3 + - drivers/cpufreq/cpufreq_times.c | 207 ++++++++++++++++++++++++++++++++ - fs/proc/base.c | 7 ++ - include/linux/cpufreq_times.h | 41 +++++++ - include/linux/sched.h | 4 + - kernel/fork.c | 7 ++ - kernel/sched/cputime.c | 7 ++ - 9 files changed, 287 insertions(+), 1 deletion(-) - create mode 100644 drivers/cpufreq/cpufreq_times.c - create mode 100644 include/linux/cpufreq_times.h - -diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig -index bff5295016ae..f711715aa579 100644 ---- a/drivers/cpufreq/Kconfig -+++ b/drivers/cpufreq/Kconfig -@@ -34,6 +34,13 @@ config CPU_FREQ_STAT - - If in doubt, say N. - -+config CPU_FREQ_TIMES -+ bool "CPU frequency time-in-state statistics" -+ help -+ Export CPU time-in-state information through procfs. -+ -+ If in doubt, say N. -+ - choice - prompt "Default CPUFreq governor" - default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1100_CPUFREQ || ARM_SA1110_CPUFREQ -diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 9a9f5ccd13d9..93d52a112cab 100644 ---- a/drivers/cpufreq/Makefile -+++ b/drivers/cpufreq/Makefile -@@ -5,7 +5,10 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o freq_table.o - # CPUfreq stats - obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o - --# CPUfreq governors -+# CPUfreq times -+obj-$(CONFIG_CPU_FREQ_TIMES) += cpufreq_times.o -+ -+# CPUfreq governors - obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o - obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o - obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o -diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -index c52d6fa32aac..a6512ee4b8cc 100644 ---- a/drivers/cpufreq/cpufreq.c -+++ b/drivers/cpufreq/cpufreq.c -@@ -16,6 +16,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -379,6 +380,7 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy, - CPUFREQ_POSTCHANGE, freqs); - - cpufreq_stats_record_transition(policy, freqs->new); -+ cpufreq_times_record_transition(freqs); - policy->cur = freqs->new; - } - } -@@ -1460,6 +1462,7 @@ static int cpufreq_online(unsigned int cpu) - goto out_destroy_policy; - - cpufreq_stats_create_table(policy); -+ cpufreq_times_create_policy(policy); - - write_lock_irqsave(&cpufreq_driver_lock, flags); - list_add(&policy->policy_list, &cpufreq_policy_list); -diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c -new file mode 100644 -index 000000000000..339a3e9cf082 ---- /dev/null -+++ b/drivers/cpufreq/cpufreq_times.c -@@ -0,0 +1,207 @@ -+/* drivers/cpufreq/cpufreq_times.c -+ * -+ * Copyright (C) 2018 Google, Inc. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */ -+ -+/** -+ * struct cpu_freqs - per-cpu frequency information -+ * @offset: start of these freqs' stats in task time_in_state array -+ * @max_state: number of entries in freq_table -+ * @last_index: index in freq_table of last frequency switched to -+ * @freq_table: list of available frequencies -+ */ -+struct cpu_freqs { -+ unsigned int offset; -+ unsigned int max_state; -+ unsigned int last_index; -+ unsigned int freq_table[0]; -+}; -+ -+static struct cpu_freqs *all_freqs[NR_CPUS]; -+ -+static unsigned int next_offset; -+ -+void cpufreq_task_times_init(struct task_struct *p) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&task_time_in_state_lock, flags); -+ p->time_in_state = NULL; -+ spin_unlock_irqrestore(&task_time_in_state_lock, flags); -+ p->max_state = 0; -+} -+ -+void cpufreq_task_times_alloc(struct task_struct *p) -+{ -+ void *temp; -+ unsigned long flags; -+ unsigned int max_state = READ_ONCE(next_offset); -+ -+ /* We use one array to avoid multiple allocs per task */ -+ temp = kcalloc(max_state, sizeof(p->time_in_state[0]), GFP_ATOMIC); -+ if (!temp) -+ return; -+ -+ spin_lock_irqsave(&task_time_in_state_lock, flags); -+ p->time_in_state = temp; -+ spin_unlock_irqrestore(&task_time_in_state_lock, flags); -+ p->max_state = max_state; -+} -+ -+/* Caller must hold task_time_in_state_lock */ -+static int cpufreq_task_times_realloc_locked(struct task_struct *p) -+{ -+ void *temp; -+ unsigned int max_state = READ_ONCE(next_offset); -+ -+ temp = krealloc(p->time_in_state, max_state * sizeof(u64), GFP_ATOMIC); -+ if (!temp) -+ return -ENOMEM; -+ p->time_in_state = temp; -+ memset(p->time_in_state + p->max_state, 0, -+ (max_state - p->max_state) * sizeof(u64)); -+ p->max_state = max_state; -+ return 0; -+} -+ -+void cpufreq_task_times_exit(struct task_struct *p) -+{ -+ unsigned long flags; -+ void *temp; -+ -+ spin_lock_irqsave(&task_time_in_state_lock, flags); -+ temp = p->time_in_state; -+ p->time_in_state = NULL; -+ spin_unlock_irqrestore(&task_time_in_state_lock, flags); -+ kfree(temp); -+} -+ -+int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, -+ struct pid *pid, struct task_struct *p) -+{ -+ unsigned int cpu, i; -+ u64 cputime; -+ unsigned long flags; -+ struct cpu_freqs *freqs; -+ struct cpu_freqs *last_freqs = NULL; -+ -+ spin_lock_irqsave(&task_time_in_state_lock, flags); -+ for_each_possible_cpu(cpu) { -+ freqs = all_freqs[cpu]; -+ if (!freqs || freqs == last_freqs) -+ continue; -+ last_freqs = freqs; -+ -+ seq_printf(m, "cpu%u\n", cpu); -+ for (i = 0; i < freqs->max_state; i++) { -+ if (freqs->freq_table[i] == CPUFREQ_ENTRY_INVALID) -+ continue; -+ cputime = 0; -+ if (freqs->offset + i < p->max_state && -+ p->time_in_state) -+ cputime = p->time_in_state[freqs->offset + i]; -+ seq_printf(m, "%u %lu\n", freqs->freq_table[i], -+ (unsigned long)nsec_to_clock_t(cputime)); -+ } -+ } -+ spin_unlock_irqrestore(&task_time_in_state_lock, flags); -+ return 0; -+} -+ -+void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) -+{ -+ unsigned long flags; -+ unsigned int state; -+ struct cpu_freqs *freqs = all_freqs[task_cpu(p)]; -+ -+ if (!freqs || p->flags & PF_EXITING) -+ return; -+ -+ state = freqs->offset + READ_ONCE(freqs->last_index); -+ -+ spin_lock_irqsave(&task_time_in_state_lock, flags); -+ if ((state < p->max_state || !cpufreq_task_times_realloc_locked(p)) && -+ p->time_in_state) -+ p->time_in_state[state] += cputime; -+ spin_unlock_irqrestore(&task_time_in_state_lock, flags); -+} -+ -+void cpufreq_times_create_policy(struct cpufreq_policy *policy) -+{ -+ int cpu, index; -+ unsigned int count = 0; -+ struct cpufreq_frequency_table *pos, *table; -+ struct cpu_freqs *freqs; -+ void *tmp; -+ -+ if (all_freqs[policy->cpu]) -+ return; -+ -+ table = policy->freq_table; -+ if (!table) -+ return; -+ -+ cpufreq_for_each_entry(pos, table) -+ count++; -+ -+ tmp = kzalloc(sizeof(*freqs) + sizeof(freqs->freq_table[0]) * count, -+ GFP_KERNEL); -+ if (!tmp) -+ return; -+ -+ freqs = tmp; -+ freqs->max_state = count; -+ -+ index = cpufreq_frequency_table_get_index(policy, policy->cur); -+ if (index >= 0) -+ WRITE_ONCE(freqs->last_index, index); -+ -+ cpufreq_for_each_entry(pos, table) -+ freqs->freq_table[pos - table] = pos->frequency; -+ -+ freqs->offset = next_offset; -+ WRITE_ONCE(next_offset, freqs->offset + count); -+ for_each_cpu(cpu, policy->related_cpus) -+ all_freqs[cpu] = freqs; -+} -+ -+void cpufreq_times_record_transition(struct cpufreq_freqs *freq) -+{ -+ int index; -+ struct cpu_freqs *freqs = all_freqs[freq->cpu]; -+ struct cpufreq_policy *policy; -+ -+ if (!freqs) -+ return; -+ -+ policy = cpufreq_cpu_get(freq->cpu); -+ if (!policy) -+ return; -+ -+ index = cpufreq_frequency_table_get_index(policy, freq->new); -+ if (index >= 0) -+ WRITE_ONCE(freqs->last_index, index); -+ -+ cpufreq_cpu_put(policy); -+} -diff --git a/fs/proc/base.c b/fs/proc/base.c -index ebea9501afb8..7d13501910ee 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -94,6 +94,7 @@ - #include - #include - #include -+#include - #include - #include "internal.h" - #include "fd.h" -@@ -3091,6 +3092,9 @@ static const struct pid_entry tgid_base_stuff[] = { - #ifdef CONFIG_LIVEPATCH - ONE("patch_state", S_IRUSR, proc_pid_patch_state), - #endif -+#ifdef CONFIG_CPU_FREQ_TIMES -+ ONE("time_in_state", 0444, proc_time_in_state_show), -+#endif - #ifdef CONFIG_STACKLEAK_METRICS - ONE("stack_depth", S_IRUGO, proc_stack_depth), - #endif -@@ -3487,6 +3491,9 @@ static const struct pid_entry tid_base_stuff[] = { - #ifdef CONFIG_PROC_PID_ARCH_STATUS - ONE("arch_status", S_IRUGO, proc_pid_arch_status), - #endif -+#ifdef CONFIG_CPU_FREQ_TIMES -+ ONE("time_in_state", 0444, proc_time_in_state_show), -+#endif - }; - - static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) -diff --git a/include/linux/cpufreq_times.h b/include/linux/cpufreq_times.h -new file mode 100644 -index 000000000000..bfef6e62c68a ---- /dev/null -+++ b/include/linux/cpufreq_times.h -@@ -0,0 +1,41 @@ -+/* drivers/cpufreq/cpufreq_times.c -+ * -+ * Copyright (C) 2018 Google, Inc. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+#ifndef _LINUX_CPUFREQ_TIMES_H -+#define _LINUX_CPUFREQ_TIMES_H -+ -+#include -+#include -+ -+#ifdef CONFIG_CPU_FREQ_TIMES -+void cpufreq_task_times_init(struct task_struct *p); -+void cpufreq_task_times_alloc(struct task_struct *p); -+void cpufreq_task_times_exit(struct task_struct *p); -+int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, -+ struct pid *pid, struct task_struct *p); -+void cpufreq_acct_update_power(struct task_struct *p, u64 cputime); -+void cpufreq_times_create_policy(struct cpufreq_policy *policy); -+void cpufreq_times_record_transition(struct cpufreq_freqs *freq); -+#else -+static inline void cpufreq_task_times_init(struct task_struct *p) {} -+static inline void cpufreq_task_times_alloc(struct task_struct *p) {} -+static inline void cpufreq_task_times_exit(struct task_struct *p) {} -+static inline void cpufreq_acct_update_power(struct task_struct *p, -+ u64 cputime) {} -+static inline void cpufreq_times_create_policy(struct cpufreq_policy *policy) {} -+static inline void cpufreq_times_record_transition( -+ struct cpufreq_freqs *freq) {} -+#endif /* CONFIG_CPU_FREQ_TIMES */ -+#endif /* _LINUX_CPUFREQ_TIMES_H */ -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 2c2e56bd8913..16c499ca096b 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -840,6 +840,10 @@ struct task_struct { - u64 stimescaled; - #endif - u64 gtime; -+#ifdef CONFIG_CPU_FREQ_TIMES -+ u64 *time_in_state; -+ unsigned int max_state; -+#endif - struct prev_cputime prev_cputime; - #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN - struct vtime vtime; -diff --git a/kernel/fork.c b/kernel/fork.c -index bcdf53125210..d8cba7583875 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -93,6 +93,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -451,6 +452,8 @@ void put_task_stack(struct task_struct *tsk) - - void free_task(struct task_struct *tsk) - { -+ cpufreq_task_times_exit(tsk); -+ - #ifndef CONFIG_THREAD_INFO_IN_TASK - /* - * The task is finally done with both the stack and thread_info, -@@ -1852,6 +1855,8 @@ static __latent_entropy struct task_struct *copy_process( - if (!p) - goto fork_out; - -+ cpufreq_task_times_init(p); -+ - /* - * This _must_ happen before we call free_task(), i.e. before we jump - * to any of the bad_fork_* labels. This is to avoid freeing -@@ -2369,6 +2374,8 @@ long _do_fork(struct kernel_clone_args *args) - if (IS_ERR(p)) - return PTR_ERR(p); - -+ cpufreq_task_times_alloc(p); -+ - /* - * Do this prior waking up the new thread - the thread pointer - * might get invalid after that point, if the thread exits quickly. -diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c -index 46ed4e1383e2..fc49c1e169d9 100644 ---- a/kernel/sched/cputime.c -+++ b/kernel/sched/cputime.c -@@ -2,6 +2,7 @@ - /* - * Simple CPU accounting cgroup controller - */ -+#include - #include "sched.h" - - #ifdef CONFIG_IRQ_TIME_ACCOUNTING -@@ -129,6 +130,9 @@ void account_user_time(struct task_struct *p, u64 cputime) - - /* Account for user time used */ - acct_account_cputime(p); -+ -+ /* Account power usage for user time */ -+ cpufreq_acct_update_power(p, cputime); - } - - /* -@@ -173,6 +177,9 @@ void account_system_index_time(struct task_struct *p, - - /* Account for system time used */ - acct_account_cputime(p); -+ -+ /* Account power usage for system time */ -+ cpufreq_acct_update_power(p, cputime); - } - - /* diff --git a/patches/ANDROID-create-build.configs-for-allmodconfig.patch b/patches/ANDROID-create-build.configs-for-allmodconfig.patch deleted file mode 100644 index 53cf4b565012b3d7115c015fbe14092ab9e3de58..0000000000000000000000000000000000000000 --- a/patches/ANDROID-create-build.configs-for-allmodconfig.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthias Maennich -Date: Thu, 29 Aug 2019 12:41:43 +0100 -Subject: ANDROID: create build.configs for allmodconfig - -Bug: 140224784 -Change-Id: I920e8737ee596e1b80428ff9831981c775570070 -Signed-off-by: Matthias Maennich ---- - build.config.allmodconfig | 11 +++++++++++ - build.config.allmodconfig.aarch64 | 4 ++++ - build.config.allmodconfig.x86_64 | 4 ++++ - 3 files changed, 19 insertions(+) - create mode 100644 build.config.allmodconfig - create mode 100644 build.config.allmodconfig.aarch64 - create mode 100644 build.config.allmodconfig.x86_64 - -diff --git a/build.config.allmodconfig b/build.config.allmodconfig -new file mode 100644 -index 000000000000..43b1a70d5800 ---- /dev/null -+++ b/build.config.allmodconfig -@@ -0,0 +1,11 @@ -+DEFCONFIG=allmodconfig -+ -+# XFS_FS is currently broken on this branch with clang-9 -+POST_DEFCONFIG_CMDS="update_config" -+function update_config() { -+ ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \ -+ -d TEST_KMOD \ -+ -d XFS_FS -+ (cd ${OUT_DIR} && \ -+ make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig) -+} -diff --git a/build.config.allmodconfig.aarch64 b/build.config.allmodconfig.aarch64 -new file mode 100644 -index 000000000000..863ab1caddab ---- /dev/null -+++ b/build.config.allmodconfig.aarch64 -@@ -0,0 +1,4 @@ -+. ${ROOT_DIR}/common/build.config.common -+. ${ROOT_DIR}/common/build.config.aarch64 -+. ${ROOT_DIR}/common/build.config.allmodconfig -+ -diff --git a/build.config.allmodconfig.x86_64 b/build.config.allmodconfig.x86_64 -new file mode 100644 -index 000000000000..bedb3869d99b ---- /dev/null -+++ b/build.config.allmodconfig.x86_64 -@@ -0,0 +1,4 @@ -+. ${ROOT_DIR}/common/build.config.common -+. ${ROOT_DIR}/common/build.config.x86_64 -+. ${ROOT_DIR}/common/build.config.allmodconfig -+ diff --git a/patches/ANDROID-cuttlefish-gki-_defconfig-Enable-CONFIG_SDCARD_FS.patch b/patches/ANDROID-cuttlefish-gki-_defconfig-Enable-CONFIG_SDCARD_FS.patch deleted file mode 100644 index f281b1ec1b1429fd40e11fcdbd75fe067a5fd9c7..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cuttlefish-gki-_defconfig-Enable-CONFIG_SDCARD_FS.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Strachan -Date: Fri, 26 Oct 2018 10:02:08 -0700 -Subject: ANDROID: {cuttlefish,gki}_defconfig: Enable CONFIG_SDCARD_FS - -Bug: 118439987 -Change-Id: I020ec721d98c5612bfe76dcfc05caabb1f3588c1 -Signed-off-by: Alistair Strachan ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 140804afdd32..18e8f81cc0fb 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -379,6 +379,7 @@ CONFIG_VFAT_FS=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y - CONFIG_ECRYPT_FS=y -+CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y - CONFIG_PSTORE_RAM=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 65c67797fb74..eacebe96e422 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -304,6 +304,7 @@ CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y - CONFIG_PSTORE_RAM=y diff --git a/patches/ANDROID-cuttlefish-overlayfs-regression.patch b/patches/ANDROID-cuttlefish-overlayfs-regression.patch deleted file mode 100644 index a3b79ff9cdf3c390d10ec9d162a36062106b5a1f..0000000000000000000000000000000000000000 --- a/patches/ANDROID-cuttlefish-overlayfs-regression.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Salyzyn -Date: Wed, 28 Aug 2019 09:38:07 -0700 -Subject: ANDROID: cuttlefish: overlayfs: regression - -commit a77712c342a56420013625c93d8aa1501455a984 -("ANDROID: Remove unused cuttlefish build infra") caused a -regression in availability of CONFIG_OVERLAY_FS configuration. - -NB: The upstream work to add override_creds to overlayfs is - required in order to pass adb-remount-test.sh. - -Signed-off-by: Mark Salyzyn -Test: confirm overlay filesystem available in the build -Bug: 138649540 -Change-Id: I9e51475f1025f726e69c6f513099248bf452cc2d ---- - arch/x86/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index a37fa09bd107..b3dad521ee8a 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -311,6 +311,7 @@ CONFIG_FS_ENCRYPTION=y - CONFIG_QUOTA=y - CONFIG_QFMT_V2=y - CONFIG_FUSE_FS=y -+CONFIG_OVERLAY_FS=y - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_TMPFS=y diff --git a/patches/ANDROID-dm-bow-Add-dm-bow-feature.patch b/patches/ANDROID-dm-bow-Add-dm-bow-feature.patch deleted file mode 100644 index b56f8da9a8bffcf635ef7c72f4099a23c9da4bc9..0000000000000000000000000000000000000000 --- a/patches/ANDROID-dm-bow-Add-dm-bow-feature.patch +++ /dev/null @@ -1,1444 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paul Lawrence -Date: Tue, 23 Oct 2018 08:56:04 -0700 -Subject: ANDROID: dm-bow: Add dm-bow feature - -Based on https://www.redhat.com/archives/dm-devel/2019-March/msg00025.html - -Third version of dm-bow. Key changes: - -Free list added -Support for block sizes other than 4k -Handles writes during trim phase, and overlapping trims -Integer overflow error -Support trims even if underlying device doesn't -Numerous small bug fixes - -bow == backup on write - -USE CASE: - -dm-bow takes a snapshot of an existing file system before mounting. -The user may, before removing the device, commit the snapshot. -Alternatively the user may remove the device and then run a command -line utility to restore the device to its original state. - -dm-bow does not require an external device - -dm-bow efficiently uses all the available free space on the file system. - -IMPLEMENTATION: - -dm-bow can be in one of three states. - -In state one, the free blocks on the device are identified by issuing -an FSTRIM to the filesystem. - -In state two, any writes cause the overwritten data to be backup up -to the available free space. While in this state, the device can be -restored by unmounting the filesystem, removing the dm-bow device -and running a usermode tool over the underlying device. - -In state three, the changes are committed, dm-bow is in pass-through -mode and the drive can no longer be restored. - -It is planned to use this driver to enable restoration of a failed -update attempt on Android devices using ext4. - -Test: Can boot Android with userdata mounted on this device. Can commit -userdata after SUW has run. Can then reboot, make changes and roll back. - -Known issues: - -Mutex is held around entire flush operation, including lengthy I/O. Plan -is to convert to state machine with pending queues. - -Interaction with block encryption is unknown, especially with respect -to sector 0. - -Bug: 119769411 -Bug: 129280212 -Test: Dogfooded on Wahoo. - Ran under Cuttlefish, running VtsKernelBowTest & - VtsKernelCheckpointTest tests against 4.19, 4.14 & 4.9 kernels -Change-Id: Id70988bbd797ebe3e76fc175094388b423c8da8c -Signed-off-by: Paul Lawrence ---- - Documentation/device-mapper/dm-bow.txt | 99 ++ - drivers/md/Kconfig | 12 + - drivers/md/Makefile | 1 + - drivers/md/dm-bow.c | 1226 ++++++++++++++++++++++++ - 4 files changed, 1338 insertions(+) - create mode 100644 Documentation/device-mapper/dm-bow.txt - create mode 100644 drivers/md/dm-bow.c - -diff --git a/Documentation/device-mapper/dm-bow.txt b/Documentation/device-mapper/dm-bow.txt -new file mode 100644 -index 000000000000..e3fc4d22e0f4 ---- /dev/null -+++ b/Documentation/device-mapper/dm-bow.txt -@@ -0,0 +1,99 @@ -+dm_bow (backup on write) -+======================== -+ -+dm_bow is a device mapper driver that uses the free space on a device to back up -+data that is overwritten. The changes can then be committed by a simple state -+change, or rolled back by removing the dm_bow device and running a command line -+utility over the underlying device. -+ -+dm_bow has three states, set by writing ‘1’ or ‘2’ to /sys/block/dm-?/bow/state. -+It is only possible to go from state 0 (initial state) to state 1, and then from -+state 1 to state 2. -+ -+State 0: dm_bow collects all trims to the device and assumes that these mark -+free space on the overlying file system that can be safely used. Typically the -+mount code would create the dm_bow device, mount the file system, call the -+FITRIM ioctl on the file system then switch to state 1. These trims are not -+propagated to the underlying device. -+ -+State 1: All writes to the device cause the underlying data to be backed up to -+the free (trimmed) area as needed in such a way as they can be restored. -+However, the writes, with one exception, then happen exactly as they would -+without dm_bow, so the device is always in a good final state. The exception is -+that sector 0 is used to keep a log of the latest changes, both to indicate that -+we are in this state and to allow rollback. See below for all details. If there -+isn't enough free space, writes are failed with -ENOSPC. -+ -+State 2: The transition to state 2 triggers replacing the special sector 0 with -+the normal sector 0, and the freeing of all state information. dm_bow then -+becomes a pass-through driver, allowing the device to continue to be used with -+minimal performance impact. -+ -+Usage -+===== -+dm-bow takes one command line parameter, the name of the underlying device. -+ -+dm-bow will typically be used in the following way. dm-bow will be loaded with a -+suitable underlying device and the resultant device will be mounted. A file -+system trim will be issued via the FITRIM ioctl, then the device will be -+switched to state 1. The file system will now be used as normal. At some point, -+the changes can either be committed by switching to state 2, or rolled back by -+unmounting the file system, removing the dm-bow device and running the command -+line utility. Note that rebooting the device will be equivalent to unmounting -+and removing, but the command line utility must still be run -+ -+Details of operation in state 1 -+=============================== -+ -+dm_bow maintains a type for all sectors. A sector can be any of: -+ -+SECTOR0 -+SECTOR0_CURRENT -+UNCHANGED -+FREE -+CHANGED -+BACKUP -+ -+SECTOR0 is the first sector on the device, and is used to hold the log of -+changes. This is the one exception. -+ -+SECTOR0_CURRENT is a sector picked from the FREE sectors, and is where reads and -+writes from the true sector zero are redirected to. Note that like any backup -+sector, if the sector is written to directly, it must be moved again. -+ -+UNCHANGED means that the sector has not been changed since we entered state 1. -+Thus if it is written to or trimmed, the contents must first be backed up. -+ -+FREE means that the sector was trimmed in state 0 and has not yet been written -+to or used for backup. On being written to, a FREE sector is changed to CHANGED. -+ -+CHANGED means that the sector has been modified, and can be further modified -+without further backup. -+ -+BACKUP means that this is a free sector being used as a backup. On being written -+to, the contents must first be backed up again. -+ -+All backup operations are logged to the first sector. The log sector has the -+format: -+-------------------------------------------------------- -+| Magic | Count | Sequence | Log entry | Log entry | … -+-------------------------------------------------------- -+ -+Magic is a magic number. Count is the number of log entries. Sequence is 0 -+initially. A log entry is -+ -+----------------------------------- -+| Source | Dest | Size | Checksum | -+----------------------------------- -+ -+When SECTOR0 is full, the log sector is backed up and another empty log sector -+created with sequence number one higher. The first entry in any log entry with -+sequence > 0 therefore must be the log of the backing up of the previous log -+sector. Note that sequence is not strictly needed, but is a useful sanity check -+and potentially limits the time spent trying to restore a corrupted snapshot. -+ -+On entering state 1, dm_bow has a list of free sectors. All other sectors are -+unchanged. Sector0_current is selected from the free sectors and the contents of -+sector 0 are copied there. The sector 0 is backed up, which triggers the first -+log entry to be written. -+ -diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig -index a744ba61ad21..2bce42552769 100644 ---- a/drivers/md/Kconfig -+++ b/drivers/md/Kconfig -@@ -608,4 +608,16 @@ config DM_ZONED - - If unsure, say N. - -+config DM_BOW -+ tristate "Backup block device" -+ depends on BLK_DEV_DM -+ select DM_BUFIO -+ ---help--- -+ This device-mapper target takes a device and keeps a log of all -+ changes using free blocks identified by issuing a trim command. -+ This can then be restored by running a command line utility, -+ or committed by simply replacing the target. -+ -+ If unsure, say N. -+ - endif # MD -diff --git a/drivers/md/Makefile b/drivers/md/Makefile -index 356b32d6b158..a9a602dfc4a3 100644 ---- a/drivers/md/Makefile -+++ b/drivers/md/Makefile -@@ -71,6 +71,7 @@ obj-$(CONFIG_DM_LOG_WRITES) += dm-log-writes.o - obj-$(CONFIG_DM_INTEGRITY) += dm-integrity.o - obj-$(CONFIG_DM_ZONED) += dm-zoned.o - obj-$(CONFIG_DM_WRITECACHE) += dm-writecache.o -+obj-$(CONFIG_DM_BOW) += dm-bow.o - - ifeq ($(CONFIG_DM_INIT),y) - dm-mod-objs += dm-init.o -diff --git a/drivers/md/dm-bow.c b/drivers/md/dm-bow.c -new file mode 100644 -index 000000000000..0d176aa140df ---- /dev/null -+++ b/drivers/md/dm-bow.c -@@ -0,0 +1,1226 @@ -+/* -+ * Copyright (C) 2018 Google Limited. -+ * -+ * This file is released under the GPL. -+ */ -+ -+#include "dm.h" -+#include "dm-core.h" -+ -+#include -+#include -+#include -+ -+#define DM_MSG_PREFIX "bow" -+ -+struct log_entry { -+ u64 source; -+ u64 dest; -+ u32 size; -+ u32 checksum; -+} __packed; -+ -+struct log_sector { -+ u32 magic; -+ u16 header_version; -+ u16 header_size; -+ u32 block_size; -+ u32 count; -+ u32 sequence; -+ sector_t sector0; -+ struct log_entry entries[]; -+} __packed; -+ -+/* -+ * MAGIC is BOW in ascii -+ */ -+#define MAGIC 0x00574f42 -+#define HEADER_VERSION 0x0100 -+ -+/* -+ * A sorted set of ranges representing the state of the data on the device. -+ * Use an rb_tree for fast lookup of a given sector -+ * Consecutive ranges are always of different type - operations on this -+ * set must merge matching consecutive ranges. -+ * -+ * Top range is always of type TOP -+ */ -+struct bow_range { -+ struct rb_node node; -+ sector_t sector; -+ enum { -+ INVALID, /* Type not set */ -+ SECTOR0, /* First sector - holds log record */ -+ SECTOR0_CURRENT,/* Live contents of sector0 */ -+ UNCHANGED, /* Original contents */ -+ TRIMMED, /* Range has been trimmed */ -+ CHANGED, /* Range has been changed */ -+ BACKUP, /* Range is being used as a backup */ -+ TOP, /* Final range - sector is size of device */ -+ } type; -+ struct list_head trimmed_list; /* list of TRIMMED ranges */ -+}; -+ -+static const char * const readable_type[] = { -+ "Invalid", -+ "Sector0", -+ "Sector0_current", -+ "Unchanged", -+ "Free", -+ "Changed", -+ "Backup", -+ "Top", -+}; -+ -+enum state { -+ TRIM, -+ CHECKPOINT, -+ COMMITTED, -+}; -+ -+struct bow_context { -+ struct dm_dev *dev; -+ u32 block_size; -+ u32 block_shift; -+ struct workqueue_struct *workqueue; -+ struct dm_bufio_client *bufio; -+ struct mutex ranges_lock; /* Hold to access this struct and/or ranges */ -+ struct rb_root ranges; -+ struct dm_kobject_holder kobj_holder; /* for sysfs attributes */ -+ atomic_t state; /* One of the enum state values above */ -+ u64 trims_total; -+ struct log_sector *log_sector; -+ struct list_head trimmed_list; -+ bool forward_trims; -+}; -+ -+sector_t range_top(struct bow_range *br) -+{ -+ return container_of(rb_next(&br->node), struct bow_range, node) -+ ->sector; -+} -+ -+u64 range_size(struct bow_range *br) -+{ -+ return (range_top(br) - br->sector) * SECTOR_SIZE; -+} -+ -+static sector_t bvec_top(struct bvec_iter *bi_iter) -+{ -+ return bi_iter->bi_sector + bi_iter->bi_size / SECTOR_SIZE; -+} -+ -+/* -+ * Find the first range that overlaps with bi_iter -+ * bi_iter is set to the size of the overlapping sub-range -+ */ -+static struct bow_range *find_first_overlapping_range(struct rb_root *ranges, -+ struct bvec_iter *bi_iter) -+{ -+ struct rb_node *node = ranges->rb_node; -+ struct bow_range *br; -+ -+ while (node) { -+ br = container_of(node, struct bow_range, node); -+ -+ if (br->sector <= bi_iter->bi_sector -+ && bi_iter->bi_sector < range_top(br)) -+ break; -+ -+ if (bi_iter->bi_sector < br->sector) -+ node = node->rb_left; -+ else -+ node = node->rb_right; -+ } -+ -+ WARN_ON(!node); -+ if (!node) -+ return NULL; -+ -+ if (range_top(br) - bi_iter->bi_sector -+ < bi_iter->bi_size >> SECTOR_SHIFT) -+ bi_iter->bi_size = (range_top(br) - bi_iter->bi_sector) -+ << SECTOR_SHIFT; -+ -+ return br; -+} -+ -+void add_before(struct rb_root *ranges, struct bow_range *new_br, -+ struct bow_range *existing) -+{ -+ struct rb_node *parent = &(existing->node); -+ struct rb_node **link = &(parent->rb_left); -+ -+ while (*link) { -+ parent = *link; -+ link = &((*link)->rb_right); -+ } -+ -+ rb_link_node(&new_br->node, parent, link); -+ rb_insert_color(&new_br->node, ranges); -+} -+ -+/* -+ * Given a range br returned by find_first_overlapping_range, split br into a -+ * leading range, a range matching the bi_iter and a trailing range. -+ * Leading and trailing may end up size 0 and will then be deleted. The -+ * new range matching the bi_iter is then returned and should have its type -+ * and type specific fields populated. -+ * If bi_iter runs off the end of the range, bi_iter is truncated accordingly -+ */ -+static int split_range(struct bow_context *bc, struct bow_range **br, -+ struct bvec_iter *bi_iter) -+{ -+ struct bow_range *new_br; -+ -+ if (bi_iter->bi_sector < (*br)->sector) { -+ WARN_ON(true); -+ return BLK_STS_IOERR; -+ } -+ -+ if (bi_iter->bi_sector > (*br)->sector) { -+ struct bow_range *leading_br = -+ kzalloc(sizeof(*leading_br), GFP_KERNEL); -+ -+ if (!leading_br) -+ return BLK_STS_RESOURCE; -+ -+ *leading_br = **br; -+ if (leading_br->type == TRIMMED) -+ list_add(&leading_br->trimmed_list, &bc->trimmed_list); -+ -+ add_before(&bc->ranges, leading_br, *br); -+ (*br)->sector = bi_iter->bi_sector; -+ } -+ -+ if (bvec_top(bi_iter) >= range_top(*br)) { -+ bi_iter->bi_size = (range_top(*br) - (*br)->sector) -+ * SECTOR_SIZE; -+ return BLK_STS_OK; -+ } -+ -+ /* new_br will be the beginning, existing br will be the tail */ -+ new_br = kzalloc(sizeof(*new_br), GFP_KERNEL); -+ if (!new_br) -+ return BLK_STS_RESOURCE; -+ -+ new_br->sector = (*br)->sector; -+ (*br)->sector = bvec_top(bi_iter); -+ add_before(&bc->ranges, new_br, *br); -+ *br = new_br; -+ -+ return BLK_STS_OK; -+} -+ -+/* -+ * Sets type of a range. May merge range into surrounding ranges -+ * Since br may be invalidated, always sets br to NULL to prevent -+ * usage after this is called -+ */ -+static void set_type(struct bow_context *bc, struct bow_range **br, int type) -+{ -+ struct bow_range *prev = container_of(rb_prev(&(*br)->node), -+ struct bow_range, node); -+ struct bow_range *next = container_of(rb_next(&(*br)->node), -+ struct bow_range, node); -+ -+ if ((*br)->type == TRIMMED) { -+ bc->trims_total -= range_size(*br); -+ list_del(&(*br)->trimmed_list); -+ } -+ -+ if (type == TRIMMED) { -+ bc->trims_total += range_size(*br); -+ list_add(&(*br)->trimmed_list, &bc->trimmed_list); -+ } -+ -+ (*br)->type = type; -+ -+ if (next->type == type) { -+ if (type == TRIMMED) -+ list_del(&next->trimmed_list); -+ rb_erase(&next->node, &bc->ranges); -+ kfree(next); -+ } -+ -+ if (prev->type == type) { -+ if (type == TRIMMED) -+ list_del(&(*br)->trimmed_list); -+ rb_erase(&(*br)->node, &bc->ranges); -+ kfree(*br); -+ } -+ -+ *br = NULL; -+} -+ -+static struct bow_range *find_free_range(struct bow_context *bc) -+{ -+ if (list_empty(&bc->trimmed_list)) { -+ DMERR("Unable to find free space to back up to"); -+ return NULL; -+ } -+ -+ return list_first_entry(&bc->trimmed_list, struct bow_range, -+ trimmed_list); -+} -+ -+static sector_t sector_to_page(struct bow_context const *bc, sector_t sector) -+{ -+ WARN_ON(sector % (bc->block_size / SECTOR_SIZE) != 0); -+ return sector >> (bc->block_shift - SECTOR_SHIFT); -+} -+ -+static int copy_data(struct bow_context const *bc, -+ struct bow_range *source, struct bow_range *dest, -+ u32 *checksum) -+{ -+ int i; -+ -+ if (range_size(source) != range_size(dest)) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ -+ if (checksum) -+ *checksum = sector_to_page(bc, source->sector); -+ -+ for (i = 0; i < range_size(source) >> bc->block_shift; ++i) { -+ struct dm_buffer *read_buffer, *write_buffer; -+ u8 *read, *write; -+ sector_t page = sector_to_page(bc, source->sector) + i; -+ -+ read = dm_bufio_read(bc->bufio, page, &read_buffer); -+ if (IS_ERR(read)) { -+ DMERR("Cannot read page %lu", page); -+ return PTR_ERR(read); -+ } -+ -+ if (checksum) -+ *checksum = crc32(*checksum, read, bc->block_size); -+ -+ write = dm_bufio_new(bc->bufio, -+ sector_to_page(bc, dest->sector) + i, -+ &write_buffer); -+ if (IS_ERR(write)) { -+ DMERR("Cannot write sector"); -+ dm_bufio_release(read_buffer); -+ return PTR_ERR(write); -+ } -+ -+ memcpy(write, read, bc->block_size); -+ -+ dm_bufio_mark_buffer_dirty(write_buffer); -+ dm_bufio_release(write_buffer); -+ dm_bufio_release(read_buffer); -+ } -+ -+ dm_bufio_write_dirty_buffers(bc->bufio); -+ return BLK_STS_OK; -+} -+ -+/****** logging functions ******/ -+ -+static int add_log_entry(struct bow_context *bc, sector_t source, sector_t dest, -+ unsigned int size, u32 checksum); -+ -+static int backup_log_sector(struct bow_context *bc) -+{ -+ struct bow_range *first_br, *free_br; -+ struct bvec_iter bi_iter; -+ u32 checksum = 0; -+ int ret; -+ -+ first_br = container_of(rb_first(&bc->ranges), struct bow_range, node); -+ -+ if (first_br->type != SECTOR0) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ -+ if (range_size(first_br) != bc->block_size) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ -+ free_br = find_free_range(bc); -+ /* No space left - return this error to userspace */ -+ if (!free_br) -+ return BLK_STS_NOSPC; -+ bi_iter.bi_sector = free_br->sector; -+ bi_iter.bi_size = bc->block_size; -+ ret = split_range(bc, &free_br, &bi_iter); -+ if (ret) -+ return ret; -+ if (bi_iter.bi_size != bc->block_size) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ -+ ret = copy_data(bc, first_br, free_br, &checksum); -+ if (ret) -+ return ret; -+ -+ bc->log_sector->count = 0; -+ bc->log_sector->sequence++; -+ ret = add_log_entry(bc, first_br->sector, free_br->sector, -+ range_size(first_br), checksum); -+ if (ret) -+ return ret; -+ -+ set_type(bc, &free_br, BACKUP); -+ return BLK_STS_OK; -+} -+ -+static int add_log_entry(struct bow_context *bc, sector_t source, sector_t dest, -+ unsigned int size, u32 checksum) -+{ -+ struct dm_buffer *sector_buffer; -+ u8 *sector; -+ -+ if (sizeof(struct log_sector) -+ + sizeof(struct log_entry) * (bc->log_sector->count + 1) -+ > bc->block_size) { -+ int ret = backup_log_sector(bc); -+ -+ if (ret) -+ return ret; -+ } -+ -+ sector = dm_bufio_new(bc->bufio, 0, §or_buffer); -+ if (IS_ERR(sector)) { -+ DMERR("Cannot write boot sector"); -+ dm_bufio_release(sector_buffer); -+ return BLK_STS_NOSPC; -+ } -+ -+ bc->log_sector->entries[bc->log_sector->count].source = source; -+ bc->log_sector->entries[bc->log_sector->count].dest = dest; -+ bc->log_sector->entries[bc->log_sector->count].size = size; -+ bc->log_sector->entries[bc->log_sector->count].checksum = checksum; -+ bc->log_sector->count++; -+ -+ memcpy(sector, bc->log_sector, bc->block_size); -+ dm_bufio_mark_buffer_dirty(sector_buffer); -+ dm_bufio_release(sector_buffer); -+ dm_bufio_write_dirty_buffers(bc->bufio); -+ return BLK_STS_OK; -+} -+ -+static int prepare_log(struct bow_context *bc) -+{ -+ struct bow_range *free_br, *first_br; -+ struct bvec_iter bi_iter; -+ u32 checksum = 0; -+ int ret; -+ -+ /* Carve out first sector as log sector */ -+ first_br = container_of(rb_first(&bc->ranges), struct bow_range, node); -+ if (first_br->type != UNCHANGED) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ -+ if (range_size(first_br) < bc->block_size) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ bi_iter.bi_sector = 0; -+ bi_iter.bi_size = bc->block_size; -+ ret = split_range(bc, &first_br, &bi_iter); -+ if (ret) -+ return ret; -+ first_br->type = SECTOR0; -+ if (range_size(first_br) != bc->block_size) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ -+ /* Find free sector for active sector0 reads/writes */ -+ free_br = find_free_range(bc); -+ if (!free_br) -+ return BLK_STS_NOSPC; -+ bi_iter.bi_sector = free_br->sector; -+ bi_iter.bi_size = bc->block_size; -+ ret = split_range(bc, &free_br, &bi_iter); -+ if (ret) -+ return ret; -+ free_br->type = SECTOR0_CURRENT; -+ -+ /* Copy data */ -+ ret = copy_data(bc, first_br, free_br, NULL); -+ if (ret) -+ return ret; -+ -+ bc->log_sector->sector0 = free_br->sector; -+ -+ /* Find free sector to back up original sector zero */ -+ free_br = find_free_range(bc); -+ if (!free_br) -+ return BLK_STS_NOSPC; -+ bi_iter.bi_sector = free_br->sector; -+ bi_iter.bi_size = bc->block_size; -+ ret = split_range(bc, &free_br, &bi_iter); -+ if (ret) -+ return ret; -+ -+ /* Back up */ -+ ret = copy_data(bc, first_br, free_br, &checksum); -+ if (ret) -+ return ret; -+ -+ /* -+ * Set up our replacement boot sector - it will get written when we -+ * add the first log entry, which we do immediately -+ */ -+ bc->log_sector->magic = MAGIC; -+ bc->log_sector->header_version = HEADER_VERSION; -+ bc->log_sector->header_size = sizeof(*bc->log_sector); -+ bc->log_sector->block_size = bc->block_size; -+ bc->log_sector->count = 0; -+ bc->log_sector->sequence = 0; -+ -+ /* Add log entry */ -+ ret = add_log_entry(bc, first_br->sector, free_br->sector, -+ range_size(first_br), checksum); -+ if (ret) -+ return ret; -+ -+ set_type(bc, &free_br, BACKUP); -+ return BLK_STS_OK; -+} -+ -+static struct bow_range *find_sector0_current(struct bow_context *bc) -+{ -+ struct bvec_iter bi_iter; -+ -+ bi_iter.bi_sector = bc->log_sector->sector0; -+ bi_iter.bi_size = bc->block_size; -+ return find_first_overlapping_range(&bc->ranges, &bi_iter); -+} -+ -+/****** sysfs interface functions ******/ -+ -+static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, -+ char *buf) -+{ -+ struct bow_context *bc = container_of(kobj, struct bow_context, -+ kobj_holder.kobj); -+ -+ return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&bc->state)); -+} -+ -+static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct bow_context *bc = container_of(kobj, struct bow_context, -+ kobj_holder.kobj); -+ enum state state, original_state; -+ int ret; -+ -+ state = buf[0] - '0'; -+ if (state < TRIM || state > COMMITTED) { -+ DMERR("State value %d out of range", state); -+ return -EINVAL; -+ } -+ -+ mutex_lock(&bc->ranges_lock); -+ original_state = atomic_read(&bc->state); -+ if (state != original_state + 1) { -+ DMERR("Invalid state change from %d to %d", -+ original_state, state); -+ ret = -EINVAL; -+ goto bad; -+ } -+ -+ DMINFO("Switching to state %s", state == CHECKPOINT ? "Checkpoint" -+ : state == COMMITTED ? "Committed" : "Unknown"); -+ -+ if (state == CHECKPOINT) { -+ ret = prepare_log(bc); -+ if (ret) { -+ DMERR("Failed to switch to checkpoint state"); -+ goto bad; -+ } -+ } else if (state == COMMITTED) { -+ struct bow_range *br = find_sector0_current(bc); -+ struct bow_range *sector0_br = -+ container_of(rb_first(&bc->ranges), struct bow_range, -+ node); -+ -+ ret = copy_data(bc, br, sector0_br, 0); -+ if (ret) { -+ DMERR("Failed to switch to committed state"); -+ goto bad; -+ } -+ } -+ atomic_inc(&bc->state); -+ ret = count; -+ -+bad: -+ mutex_unlock(&bc->ranges_lock); -+ return ret; -+} -+ -+static ssize_t free_show(struct kobject *kobj, struct kobj_attribute *attr, -+ char *buf) -+{ -+ struct bow_context *bc = container_of(kobj, struct bow_context, -+ kobj_holder.kobj); -+ u64 trims_total; -+ -+ mutex_lock(&bc->ranges_lock); -+ trims_total = bc->trims_total; -+ mutex_unlock(&bc->ranges_lock); -+ -+ return scnprintf(buf, PAGE_SIZE, "%llu\n", trims_total); -+} -+ -+static struct kobj_attribute attr_state = __ATTR_RW(state); -+static struct kobj_attribute attr_free = __ATTR_RO(free); -+ -+static struct attribute *bow_attrs[] = { -+ &attr_state.attr, -+ &attr_free.attr, -+ NULL -+}; -+ -+static struct kobj_type bow_ktype = { -+ .sysfs_ops = &kobj_sysfs_ops, -+ .default_attrs = bow_attrs, -+ .release = dm_kobject_release -+}; -+ -+/****** constructor/destructor ******/ -+ -+static void dm_bow_dtr(struct dm_target *ti) -+{ -+ struct bow_context *bc = (struct bow_context *) ti->private; -+ struct kobject *kobj; -+ -+ while (rb_first(&bc->ranges)) { -+ struct bow_range *br = container_of(rb_first(&bc->ranges), -+ struct bow_range, node); -+ -+ rb_erase(&br->node, &bc->ranges); -+ kfree(br); -+ } -+ if (bc->workqueue) -+ destroy_workqueue(bc->workqueue); -+ if (bc->bufio) -+ dm_bufio_client_destroy(bc->bufio); -+ -+ kobj = &bc->kobj_holder.kobj; -+ if (kobj->state_initialized) { -+ kobject_put(kobj); -+ wait_for_completion(dm_get_completion_from_kobject(kobj)); -+ } -+ -+ kfree(bc->log_sector); -+ kfree(bc); -+} -+ -+static int dm_bow_ctr(struct dm_target *ti, unsigned int argc, char **argv) -+{ -+ struct bow_context *bc; -+ struct bow_range *br; -+ int ret; -+ struct mapped_device *md = dm_table_get_md(ti->table); -+ -+ if (argc != 1) { -+ ti->error = "Invalid argument count"; -+ return -EINVAL; -+ } -+ -+ bc = kzalloc(sizeof(*bc), GFP_KERNEL); -+ if (!bc) { -+ ti->error = "Cannot allocate bow context"; -+ return -ENOMEM; -+ } -+ -+ ti->num_flush_bios = 1; -+ ti->num_discard_bios = 1; -+ ti->num_write_same_bios = 1; -+ ti->private = bc; -+ -+ ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), -+ &bc->dev); -+ if (ret) { -+ ti->error = "Device lookup failed"; -+ goto bad; -+ } -+ -+ if (bc->dev->bdev->bd_queue->limits.max_discard_sectors == 0) { -+ bc->dev->bdev->bd_queue->limits.discard_granularity = 1 << 12; -+ bc->dev->bdev->bd_queue->limits.max_hw_discard_sectors = 1 << 15; -+ bc->dev->bdev->bd_queue->limits.max_discard_sectors = 1 << 15; -+ bc->forward_trims = false; -+ } else { -+ bc->forward_trims = true; -+ } -+ -+ bc->block_size = bc->dev->bdev->bd_queue->limits.logical_block_size; -+ bc->block_shift = ilog2(bc->block_size); -+ bc->log_sector = kzalloc(bc->block_size, GFP_KERNEL); -+ if (!bc->log_sector) { -+ ti->error = "Cannot allocate log sector"; -+ goto bad; -+ } -+ -+ init_completion(&bc->kobj_holder.completion); -+ ret = kobject_init_and_add(&bc->kobj_holder.kobj, &bow_ktype, -+ &disk_to_dev(dm_disk(md))->kobj, "%s", -+ "bow"); -+ if (ret) { -+ ti->error = "Cannot create sysfs node"; -+ goto bad; -+ } -+ -+ mutex_init(&bc->ranges_lock); -+ bc->ranges = RB_ROOT; -+ bc->bufio = dm_bufio_client_create(bc->dev->bdev, bc->block_size, 1, 0, -+ NULL, NULL); -+ if (IS_ERR(bc->bufio)) { -+ ti->error = "Cannot initialize dm-bufio"; -+ ret = PTR_ERR(bc->bufio); -+ bc->bufio = NULL; -+ goto bad; -+ } -+ -+ bc->workqueue = alloc_workqueue("dm-bow", -+ WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM -+ | WQ_UNBOUND, num_online_cpus()); -+ if (!bc->workqueue) { -+ ti->error = "Cannot allocate workqueue"; -+ ret = -ENOMEM; -+ goto bad; -+ } -+ -+ INIT_LIST_HEAD(&bc->trimmed_list); -+ -+ br = kzalloc(sizeof(*br), GFP_KERNEL); -+ if (!br) { -+ ti->error = "Cannot allocate ranges"; -+ ret = -ENOMEM; -+ goto bad; -+ } -+ -+ br->sector = ti->len; -+ br->type = TOP; -+ rb_link_node(&br->node, NULL, &bc->ranges.rb_node); -+ rb_insert_color(&br->node, &bc->ranges); -+ -+ br = kzalloc(sizeof(*br), GFP_KERNEL); -+ if (!br) { -+ ti->error = "Cannot allocate ranges"; -+ ret = -ENOMEM; -+ goto bad; -+ } -+ -+ br->sector = 0; -+ br->type = UNCHANGED; -+ rb_link_node(&br->node, bc->ranges.rb_node, -+ &bc->ranges.rb_node->rb_left); -+ rb_insert_color(&br->node, &bc->ranges); -+ -+ ti->discards_supported = true; -+ -+ return 0; -+ -+bad: -+ dm_bow_dtr(ti); -+ return ret; -+} -+ -+/****** Handle writes ******/ -+ -+static int prepare_unchanged_range(struct bow_context *bc, struct bow_range *br, -+ struct bvec_iter *bi_iter, -+ bool record_checksum) -+{ -+ struct bow_range *backup_br; -+ struct bvec_iter backup_bi; -+ sector_t log_source, log_dest; -+ unsigned int log_size; -+ u32 checksum = 0; -+ int ret; -+ int original_type; -+ sector_t sector0; -+ -+ /* Find a free range */ -+ backup_br = find_free_range(bc); -+ if (!backup_br) -+ return BLK_STS_NOSPC; -+ -+ /* Carve out a backup range. This may be smaller than the br given */ -+ backup_bi.bi_sector = backup_br->sector; -+ backup_bi.bi_size = min(range_size(backup_br), (u64) bi_iter->bi_size); -+ ret = split_range(bc, &backup_br, &backup_bi); -+ if (ret) -+ return ret; -+ -+ /* -+ * Carve out a changed range. This will not be smaller than the backup -+ * br since the backup br is smaller than the source range and iterator -+ */ -+ bi_iter->bi_size = backup_bi.bi_size; -+ ret = split_range(bc, &br, bi_iter); -+ if (ret) -+ return ret; -+ if (range_size(br) != range_size(backup_br)) { -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+ -+ -+ /* Copy data over */ -+ ret = copy_data(bc, br, backup_br, record_checksum ? &checksum : NULL); -+ if (ret) -+ return ret; -+ -+ /* Add an entry to the log */ -+ log_source = br->sector; -+ log_dest = backup_br->sector; -+ log_size = range_size(br); -+ -+ /* -+ * Set the types. Note that since set_type also amalgamates ranges -+ * we have to set both sectors to their final type before calling -+ * set_type on either -+ */ -+ original_type = br->type; -+ sector0 = backup_br->sector; -+ if (backup_br->type == TRIMMED) -+ list_del(&backup_br->trimmed_list); -+ backup_br->type = br->type == SECTOR0_CURRENT ? SECTOR0_CURRENT -+ : BACKUP; -+ br->type = CHANGED; -+ set_type(bc, &backup_br, backup_br->type); -+ -+ /* -+ * Add the log entry after marking the backup sector, since adding a log -+ * can cause another backup -+ */ -+ ret = add_log_entry(bc, log_source, log_dest, log_size, checksum); -+ if (ret) { -+ br->type = original_type; -+ return ret; -+ } -+ -+ /* Now it is safe to mark this backup successful */ -+ if (original_type == SECTOR0_CURRENT) -+ bc->log_sector->sector0 = sector0; -+ -+ set_type(bc, &br, br->type); -+ return ret; -+} -+ -+static int prepare_free_range(struct bow_context *bc, struct bow_range *br, -+ struct bvec_iter *bi_iter) -+{ -+ int ret; -+ -+ ret = split_range(bc, &br, bi_iter); -+ if (ret) -+ return ret; -+ set_type(bc, &br, CHANGED); -+ return BLK_STS_OK; -+} -+ -+static int prepare_changed_range(struct bow_context *bc, struct bow_range *br, -+ struct bvec_iter *bi_iter) -+{ -+ /* Nothing to do ... */ -+ return BLK_STS_OK; -+} -+ -+static int prepare_one_range(struct bow_context *bc, -+ struct bvec_iter *bi_iter) -+{ -+ struct bow_range *br = find_first_overlapping_range(&bc->ranges, -+ bi_iter); -+ switch (br->type) { -+ case CHANGED: -+ return prepare_changed_range(bc, br, bi_iter); -+ -+ case TRIMMED: -+ return prepare_free_range(bc, br, bi_iter); -+ -+ case UNCHANGED: -+ case BACKUP: -+ return prepare_unchanged_range(bc, br, bi_iter, true); -+ -+ /* -+ * We cannot track the checksum for the active sector0, since it -+ * may change at any point. -+ */ -+ case SECTOR0_CURRENT: -+ return prepare_unchanged_range(bc, br, bi_iter, false); -+ -+ case SECTOR0: /* Handled in the dm_bow_map */ -+ case TOP: /* Illegal - top is off the end of the device */ -+ default: -+ WARN_ON(1); -+ return BLK_STS_IOERR; -+ } -+} -+ -+struct write_work { -+ struct work_struct work; -+ struct bow_context *bc; -+ struct bio *bio; -+}; -+ -+static void bow_write(struct work_struct *work) -+{ -+ struct write_work *ww = container_of(work, struct write_work, work); -+ struct bow_context *bc = ww->bc; -+ struct bio *bio = ww->bio; -+ struct bvec_iter bi_iter = bio->bi_iter; -+ int ret = BLK_STS_OK; -+ -+ kfree(ww); -+ -+ mutex_lock(&bc->ranges_lock); -+ do { -+ ret = prepare_one_range(bc, &bi_iter); -+ bi_iter.bi_sector += bi_iter.bi_size / SECTOR_SIZE; -+ bi_iter.bi_size = bio->bi_iter.bi_size -+ - (bi_iter.bi_sector - bio->bi_iter.bi_sector) -+ * SECTOR_SIZE; -+ } while (!ret && bi_iter.bi_size); -+ -+ mutex_unlock(&bc->ranges_lock); -+ -+ if (!ret) { -+ bio_set_dev(bio, bc->dev->bdev); -+ submit_bio(bio); -+ } else { -+ DMERR("Write failure with error %d", -ret); -+ bio->bi_status = ret; -+ bio_endio(bio); -+ } -+} -+ -+static int queue_write(struct bow_context *bc, struct bio *bio) -+{ -+ struct write_work *ww = kmalloc(sizeof(*ww), GFP_NOIO | __GFP_NORETRY -+ | __GFP_NOMEMALLOC | __GFP_NOWARN); -+ if (!ww) { -+ DMERR("Failed to allocate write_work"); -+ return -ENOMEM; -+ } -+ -+ INIT_WORK(&ww->work, bow_write); -+ ww->bc = bc; -+ ww->bio = bio; -+ queue_work(bc->workqueue, &ww->work); -+ return DM_MAPIO_SUBMITTED; -+} -+ -+static int handle_sector0(struct bow_context *bc, struct bio *bio) -+{ -+ int ret = DM_MAPIO_REMAPPED; -+ -+ if (bio->bi_iter.bi_size > bc->block_size) { -+ struct bio * split = bio_split(bio, -+ bc->block_size >> SECTOR_SHIFT, -+ GFP_NOIO, -+ &fs_bio_set); -+ if (!split) { -+ DMERR("Failed to split bio"); -+ bio->bi_status = BLK_STS_RESOURCE; -+ bio_endio(bio); -+ return DM_MAPIO_SUBMITTED; -+ } -+ -+ bio_chain(split, bio); -+ split->bi_iter.bi_sector = bc->log_sector->sector0; -+ bio_set_dev(split, bc->dev->bdev); -+ submit_bio(split); -+ -+ if (bio_data_dir(bio) == WRITE) -+ ret = queue_write(bc, bio); -+ } else { -+ bio->bi_iter.bi_sector = bc->log_sector->sector0; -+ } -+ -+ return ret; -+} -+ -+static int add_trim(struct bow_context *bc, struct bio *bio) -+{ -+ struct bow_range *br; -+ struct bvec_iter bi_iter = bio->bi_iter; -+ -+ DMDEBUG("add_trim: %lu, %u", -+ bio->bi_iter.bi_sector, bio->bi_iter.bi_size); -+ -+ do { -+ br = find_first_overlapping_range(&bc->ranges, &bi_iter); -+ -+ switch (br->type) { -+ case UNCHANGED: -+ if (!split_range(bc, &br, &bi_iter)) -+ set_type(bc, &br, TRIMMED); -+ break; -+ -+ case TRIMMED: -+ /* Nothing to do */ -+ break; -+ -+ default: -+ /* No other case is legal in TRIM state */ -+ WARN_ON(true); -+ break; -+ } -+ -+ bi_iter.bi_sector += bi_iter.bi_size / SECTOR_SIZE; -+ bi_iter.bi_size = bio->bi_iter.bi_size -+ - (bi_iter.bi_sector - bio->bi_iter.bi_sector) -+ * SECTOR_SIZE; -+ -+ } while (bi_iter.bi_size); -+ -+ bio_endio(bio); -+ return DM_MAPIO_SUBMITTED; -+} -+ -+static int remove_trim(struct bow_context *bc, struct bio *bio) -+{ -+ struct bow_range *br; -+ struct bvec_iter bi_iter = bio->bi_iter; -+ -+ DMDEBUG("remove_trim: %lu, %u", -+ bio->bi_iter.bi_sector, bio->bi_iter.bi_size); -+ -+ do { -+ br = find_first_overlapping_range(&bc->ranges, &bi_iter); -+ -+ switch (br->type) { -+ case UNCHANGED: -+ /* Nothing to do */ -+ break; -+ -+ case TRIMMED: -+ if (!split_range(bc, &br, &bi_iter)) -+ set_type(bc, &br, UNCHANGED); -+ break; -+ -+ default: -+ /* No other case is legal in TRIM state */ -+ WARN_ON(true); -+ break; -+ } -+ -+ bi_iter.bi_sector += bi_iter.bi_size / SECTOR_SIZE; -+ bi_iter.bi_size = bio->bi_iter.bi_size -+ - (bi_iter.bi_sector - bio->bi_iter.bi_sector) -+ * SECTOR_SIZE; -+ -+ } while (bi_iter.bi_size); -+ -+ return DM_MAPIO_REMAPPED; -+} -+ -+int remap_unless_illegal_trim(struct bow_context *bc, struct bio *bio) -+{ -+ if (!bc->forward_trims && bio_op(bio) == REQ_OP_DISCARD) { -+ bio->bi_status = BLK_STS_NOTSUPP; -+ bio_endio(bio); -+ return DM_MAPIO_SUBMITTED; -+ } else { -+ bio_set_dev(bio, bc->dev->bdev); -+ return DM_MAPIO_REMAPPED; -+ } -+} -+ -+/****** dm interface ******/ -+ -+static int dm_bow_map(struct dm_target *ti, struct bio *bio) -+{ -+ int ret = DM_MAPIO_REMAPPED; -+ struct bow_context *bc = ti->private; -+ -+ if (likely(bc->state.counter == COMMITTED)) -+ return remap_unless_illegal_trim(bc, bio); -+ -+ if (bio_data_dir(bio) == READ && bio->bi_iter.bi_sector != 0) -+ return remap_unless_illegal_trim(bc, bio); -+ -+ if (atomic_read(&bc->state) != COMMITTED) { -+ enum state state; -+ -+ mutex_lock(&bc->ranges_lock); -+ state = atomic_read(&bc->state); -+ if (state == TRIM) { -+ if (bio_op(bio) == REQ_OP_DISCARD) -+ ret = add_trim(bc, bio); -+ else if (bio_data_dir(bio) == WRITE) -+ ret = remove_trim(bc, bio); -+ else -+ /* pass-through */; -+ } else if (state == CHECKPOINT) { -+ if (bio->bi_iter.bi_sector == 0) -+ ret = handle_sector0(bc, bio); -+ else if (bio_data_dir(bio) == WRITE) -+ ret = queue_write(bc, bio); -+ else -+ /* pass-through */; -+ } else { -+ /* pass-through */ -+ } -+ mutex_unlock(&bc->ranges_lock); -+ } -+ -+ if (ret == DM_MAPIO_REMAPPED) -+ return remap_unless_illegal_trim(bc, bio); -+ -+ return ret; -+} -+ -+static void dm_bow_tablestatus(struct dm_target *ti, char *result, -+ unsigned int maxlen) -+{ -+ char *end = result + maxlen; -+ struct bow_context *bc = ti->private; -+ struct rb_node *i; -+ int trimmed_list_length = 0; -+ int trimmed_range_count = 0; -+ struct bow_range *br; -+ -+ if (maxlen == 0) -+ return; -+ result[0] = 0; -+ -+ list_for_each_entry(br, &bc->trimmed_list, trimmed_list) -+ if (br->type == TRIMMED) { -+ ++trimmed_list_length; -+ } else { -+ scnprintf(result, end - result, -+ "ERROR: non-trimmed entry in trimmed_list"); -+ return; -+ } -+ -+ if (!rb_first(&bc->ranges)) { -+ scnprintf(result, end - result, "ERROR: Empty ranges"); -+ return; -+ } -+ -+ if (container_of(rb_first(&bc->ranges), struct bow_range, node) -+ ->sector) { -+ scnprintf(result, end - result, -+ "ERROR: First range does not start at sector 0"); -+ return; -+ } -+ -+ for (i = rb_first(&bc->ranges); i; i = rb_next(i)) { -+ struct bow_range *br = container_of(i, struct bow_range, node); -+ -+ result += scnprintf(result, end - result, "%s: %lu", -+ readable_type[br->type], br->sector); -+ if (result >= end) -+ return; -+ -+ result += scnprintf(result, end - result, "\n"); -+ if (result >= end) -+ return; -+ -+ if (br->type == TRIMMED) -+ ++trimmed_range_count; -+ -+ if (br->type == TOP) { -+ if (br->sector != ti->len) { -+ scnprintf(result, end - result, -+ "\nERROR: Top sector is incorrect"); -+ } -+ -+ if (&br->node != rb_last(&bc->ranges)) { -+ scnprintf(result, end - result, -+ "\nERROR: Top sector is not last"); -+ } -+ -+ break; -+ } -+ -+ if (!rb_next(i)) { -+ scnprintf(result, end - result, -+ "\nERROR: Last range not of type TOP"); -+ return; -+ } -+ -+ if (br->sector > range_top(br)) { -+ scnprintf(result, end - result, -+ "\nERROR: sectors out of order"); -+ return; -+ } -+ } -+ -+ if (trimmed_range_count != trimmed_list_length) -+ scnprintf(result, end - result, -+ "\nERROR: not all trimmed ranges in trimmed list"); -+} -+ -+static void dm_bow_status(struct dm_target *ti, status_type_t type, -+ unsigned int status_flags, char *result, -+ unsigned int maxlen) -+{ -+ switch (type) { -+ case STATUSTYPE_INFO: -+ if (maxlen) -+ result[0] = 0; -+ break; -+ -+ case STATUSTYPE_TABLE: -+ dm_bow_tablestatus(ti, result, maxlen); -+ break; -+ } -+} -+ -+int dm_bow_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) -+{ -+ struct bow_context *bc = ti->private; -+ struct dm_dev *dev = bc->dev; -+ -+ *bdev = dev->bdev; -+ /* Only pass ioctls through if the device sizes match exactly. */ -+ return ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT; -+} -+ -+static int dm_bow_iterate_devices(struct dm_target *ti, -+ iterate_devices_callout_fn fn, void *data) -+{ -+ struct bow_context *bc = ti->private; -+ -+ return fn(ti, bc->dev, 0, ti->len, data); -+} -+ -+static struct target_type bow_target = { -+ .name = "bow", -+ .version = {1, 1, 1}, -+ .module = THIS_MODULE, -+ .ctr = dm_bow_ctr, -+ .dtr = dm_bow_dtr, -+ .map = dm_bow_map, -+ .status = dm_bow_status, -+ .prepare_ioctl = dm_bow_prepare_ioctl, -+ .iterate_devices = dm_bow_iterate_devices, -+}; -+ -+int __init dm_bow_init(void) -+{ -+ int r = dm_register_target(&bow_target); -+ -+ if (r < 0) -+ DMERR("registering bow failed %d", r); -+ return r; -+} -+ -+void dm_bow_exit(void) -+{ -+ dm_unregister_target(&bow_target); -+} -+ -+MODULE_LICENSE("GPL"); -+ -+module_init(dm_bow_init); -+module_exit(dm_bow_exit); diff --git a/patches/ANDROID-dm-bow-Fix-32-bit-compile-errors.patch b/patches/ANDROID-dm-bow-Fix-32-bit-compile-errors.patch deleted file mode 100644 index 9f38d14bf59e592b046504d9b05a60630e4b0e2c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-dm-bow-Fix-32-bit-compile-errors.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paul Lawrence -Date: Tue, 26 Mar 2019 09:05:55 -0700 -Subject: ANDROID: dm-bow: Fix 32 bit compile errors - -See https://www.kernel.org/doc/html/v4.17/core-api/printk-formats.html - -Also 64-bit modulus not defined on 32-bit architectures - -Test: i386_defconfig and x86_64_cuttlefish_defconfig compile -Change-Id: I57b9372e12e97b9a18232191b525e7601bc57a24 -Signed-off-by: Paul Lawrence ---- - drivers/md/dm-bow.c | 21 +++++++++++++-------- - 1 file changed, 13 insertions(+), 8 deletions(-) - -diff --git a/drivers/md/dm-bow.c b/drivers/md/dm-bow.c -index 0d176aa140df..9323c7c8580d 100644 ---- a/drivers/md/dm-bow.c -+++ b/drivers/md/dm-bow.c -@@ -266,7 +266,8 @@ static struct bow_range *find_free_range(struct bow_context *bc) - - static sector_t sector_to_page(struct bow_context const *bc, sector_t sector) - { -- WARN_ON(sector % (bc->block_size / SECTOR_SIZE) != 0); -+ WARN_ON((sector & (((sector_t)1 << (bc->block_shift - SECTOR_SHIFT)) - 1)) -+ != 0); - return sector >> (bc->block_shift - SECTOR_SHIFT); - } - -@@ -291,7 +292,8 @@ static int copy_data(struct bow_context const *bc, - - read = dm_bufio_read(bc->bufio, page, &read_buffer); - if (IS_ERR(read)) { -- DMERR("Cannot read page %lu", page); -+ DMERR("Cannot read page %llu", -+ (unsigned long long)page); - return PTR_ERR(read); - } - -@@ -952,8 +954,9 @@ static int add_trim(struct bow_context *bc, struct bio *bio) - struct bow_range *br; - struct bvec_iter bi_iter = bio->bi_iter; - -- DMDEBUG("add_trim: %lu, %u", -- bio->bi_iter.bi_sector, bio->bi_iter.bi_size); -+ DMDEBUG("add_trim: %llu, %u", -+ (unsigned long long)bio->bi_iter.bi_sector, -+ bio->bi_iter.bi_size); - - do { - br = find_first_overlapping_range(&bc->ranges, &bi_iter); -@@ -990,8 +993,9 @@ static int remove_trim(struct bow_context *bc, struct bio *bio) - struct bow_range *br; - struct bvec_iter bi_iter = bio->bi_iter; - -- DMDEBUG("remove_trim: %lu, %u", -- bio->bi_iter.bi_sector, bio->bi_iter.bi_size); -+ DMDEBUG("remove_trim: %llu, %u", -+ (unsigned long long)bio->bi_iter.bi_sector, -+ bio->bi_iter.bi_size); - - do { - br = find_first_overlapping_range(&bc->ranges, &bi_iter); -@@ -1116,8 +1120,9 @@ static void dm_bow_tablestatus(struct dm_target *ti, char *result, - for (i = rb_first(&bc->ranges); i; i = rb_next(i)) { - struct bow_range *br = container_of(i, struct bow_range, node); - -- result += scnprintf(result, end - result, "%s: %lu", -- readable_type[br->type], br->sector); -+ result += scnprintf(result, end - result, "%s: %llu", -+ readable_type[br->type], -+ (unsigned long long)br->sector); - if (result >= end) - return; - diff --git a/patches/ANDROID-dma-buf-Add-support-for-mapping-buffers-with-DMA-attributes.patch b/patches/ANDROID-dma-buf-Add-support-for-mapping-buffers-with-DMA-attributes.patch deleted file mode 100644 index e6a9bcfbd24e8dfa997d56a18b3beb7fae149b27..0000000000000000000000000000000000000000 --- a/patches/ANDROID-dma-buf-Add-support-for-mapping-buffers-with-DMA-attributes.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Isaac J. Manjarres" -Date: Wed, 19 Jun 2019 15:37:13 -0700 -Subject: ANDROID: dma-buf: Add support for mapping buffers with DMA attributes - -When mapping the memory represented by a dma-buf into a device's -address space, it might be desireable to map the memory with -certain DMA attributes. Thus, introduce the dma_mapping_attrs -field in the dma_buf_attachment structure so that when -the memory is mapped with dma_buf_map_attachment, it is mapped -with the desired DMA attributes. - -Bug: 133508579 -Test: ion-unit-tests -Change-Id: Ib2e5bafdc02ae31a58ce96a82d77cc508dd71bd4 -Signed-off-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - include/linux/dma-buf.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h -index b1457e6b76d8..0458da673ec5 100644 ---- a/include/linux/dma-buf.h -+++ b/include/linux/dma-buf.h -@@ -384,6 +384,8 @@ struct dma_buf { - * @sgt: cached mapping. - * @dir: direction of cached mapping. - * @priv: exporter specific attachment data. -+ * @dma_map_attrs: DMA attributes to be used when the exporter maps the buffer -+ * through dma_buf_map_attachment. - * - * This structure holds the attachment information between the dma_buf buffer - * and its user device(s). The list contains one attachment struct per device -@@ -401,6 +403,7 @@ struct dma_buf_attachment { - struct sg_table *sgt; - enum dma_data_direction dir; - void *priv; -+ unsigned long dma_map_attrs; - }; - - /** diff --git a/patches/ANDROID-dma-buf-Add-support-for-partial-cache-maintenance.patch b/patches/ANDROID-dma-buf-Add-support-for-partial-cache-maintenance.patch deleted file mode 100644 index fa949dfd435ede6298e0f8c0092d73f88d2b8a19..0000000000000000000000000000000000000000 --- a/patches/ANDROID-dma-buf-Add-support-for-partial-cache-maintenance.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Isaac J. Manjarres" -Date: Wed, 19 Jun 2019 15:37:11 -0700 -Subject: ANDROID: dma-buf: Add support for partial cache maintenance - -In order to improve performance, allow dma-buf clients to -apply cache maintenance to only a subset of a dma-buf. - -Kernel clients will be able to use the dma_buf_begin_cpu_access_partial -and dma_buf_end_cpu_access_partial functions to only apply cache -maintenance to a range within the dma-buf. - -Bug: 133508579 -Test: ion-unit-tests -Change-Id: Icce61fc21b1542f5248daea34f713184449a62c3 -Signed-off-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - drivers/dma-buf/dma-buf.c | 40 +++++++++++++++++++++++++ - include/linux/dma-buf.h | 63 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 103 insertions(+) - -diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c -index 433d91d710e4..532a854be1b3 100644 ---- a/drivers/dma-buf/dma-buf.c -+++ b/drivers/dma-buf/dma-buf.c -@@ -957,6 +957,30 @@ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - } - EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); - -+int dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, -+ enum dma_data_direction direction, -+ unsigned int offset, unsigned int len) -+{ -+ int ret = 0; -+ -+ if (WARN_ON(!dmabuf)) -+ return -EINVAL; -+ -+ if (dmabuf->ops->begin_cpu_access_partial) -+ ret = dmabuf->ops->begin_cpu_access_partial(dmabuf, direction, -+ offset, len); -+ -+ /* Ensure that all fences are waited upon - but we first allow -+ * the native handler the chance to do so more efficiently if it -+ * chooses. A double invocation here will be reasonably cheap no-op. -+ */ -+ if (ret == 0) -+ ret = __dma_buf_begin_cpu_access(dmabuf, direction); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access_partial); -+ - /** - * dma_buf_end_cpu_access - Must be called after accessing a dma_buf from the - * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific -@@ -983,6 +1007,22 @@ int dma_buf_end_cpu_access(struct dma_buf *dmabuf, - } - EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access); - -+int dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, -+ enum dma_data_direction direction, -+ unsigned int offset, unsigned int len) -+{ -+ int ret = 0; -+ -+ WARN_ON(!dmabuf); -+ -+ if (dmabuf->ops->end_cpu_access_partial) -+ ret = dmabuf->ops->end_cpu_access_partial(dmabuf, direction, -+ offset, len); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access_partial); -+ - /** - * dma_buf_kmap - Map a page of the buffer object into kernel address space. The - * same restrictions as for kmap and friends apply. -diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h -index ec212cb27fdc..b1457e6b76d8 100644 ---- a/include/linux/dma-buf.h -+++ b/include/linux/dma-buf.h -@@ -178,6 +178,41 @@ struct dma_buf_ops { - */ - int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction); - -+ /** -+ * @begin_cpu_access_partial: -+ * -+ * This is called from dma_buf_begin_cpu_access_partial() and allows the -+ * exporter to ensure that the memory specified in the range is -+ * available for cpu access - the exporter might need to allocate or -+ * swap-in and pin the backing storage. -+ * The exporter also needs to ensure that cpu access is -+ * coherent for the access direction. The direction can be used by the -+ * exporter to optimize the cache flushing, i.e. access with a different -+ * direction (read instead of write) might return stale or even bogus -+ * data (e.g. when the exporter needs to copy the data to temporary -+ * storage). -+ * -+ * This callback is optional. -+ * -+ * FIXME: This is both called through the DMA_BUF_IOCTL_SYNC command -+ * from userspace (where storage shouldn't be pinned to avoid handing -+ * de-factor mlock rights to userspace) and for the kernel-internal -+ * users of the various kmap interfaces, where the backing storage must -+ * be pinned to guarantee that the atomic kmap calls can succeed. Since -+ * there's no in-kernel users of the kmap interfaces yet this isn't a -+ * real problem. -+ * -+ * Returns: -+ * -+ * 0 on success or a negative error code on failure. This can for -+ * example fail when the backing storage can't be allocated. Can also -+ * return -ERESTARTSYS or -EINTR when the call has been interrupted and -+ * needs to be restarted. -+ */ -+ int (*begin_cpu_access_partial)(struct dma_buf *dmabuf, -+ enum dma_data_direction, -+ unsigned int offset, unsigned int len); -+ - /** - * @end_cpu_access: - * -@@ -197,6 +232,28 @@ struct dma_buf_ops { - */ - int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction); - -+ /** -+ * @end_cpu_access_partial: -+ * -+ * This is called from dma_buf_end_cpu_access_partial() when the -+ * importer is done accessing the CPU. The exporter can use to limit -+ * cache flushing to only the range specefied and to unpin any -+ * resources pinned in @begin_cpu_access_umapped. -+ * The result of any dma_buf kmap calls after end_cpu_access_partial is -+ * undefined. -+ * -+ * This callback is optional. -+ * -+ * Returns: -+ * -+ * 0 on success or a negative error code on failure. Can return -+ * -ERESTARTSYS or -EINTR when the call has been interrupted and needs -+ * to be restarted. -+ */ -+ int (*end_cpu_access_partial)(struct dma_buf *dmabuf, -+ enum dma_data_direction, -+ unsigned int offset, unsigned int len); -+ - /** - * @mmap: - * -@@ -411,8 +468,14 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *, - enum dma_data_direction); - int dma_buf_begin_cpu_access(struct dma_buf *dma_buf, - enum dma_data_direction dir); -+int dma_buf_begin_cpu_access_partial(struct dma_buf *dma_buf, -+ enum dma_data_direction dir, -+ unsigned int offset, unsigned int len); - int dma_buf_end_cpu_access(struct dma_buf *dma_buf, - enum dma_data_direction dir); -+int dma_buf_end_cpu_access_partial(struct dma_buf *dma_buf, -+ enum dma_data_direction dir, -+ unsigned int offset, unsigned int len); - void *dma_buf_kmap(struct dma_buf *, unsigned long); - void dma_buf_kunmap(struct dma_buf *, unsigned long, void *); - diff --git a/patches/ANDROID-dma-buf-Add-support-to-get-flags-associated-with-a-buffer.patch b/patches/ANDROID-dma-buf-Add-support-to-get-flags-associated-with-a-buffer.patch deleted file mode 100644 index 5f2b3d17985c147c4c8ee29b7bf78113111fa16b..0000000000000000000000000000000000000000 --- a/patches/ANDROID-dma-buf-Add-support-to-get-flags-associated-with-a-buffer.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Isaac J. Manjarres" -Date: Wed, 19 Jun 2019 15:37:12 -0700 -Subject: ANDROID: dma-buf: Add support to get flags associated with a buffer - -Allow kernel clients to get the flags associated with a buffer -that is wrapped by a dma-buf. This information can be used to -communicate the type of memory associated with the -buffer(e.g. uncached vs cached memory). - -Bug: 133508579 -Test: ion-unit-tests -Change-Id: I82eab8beb738b258616c22a01080615d7ffb6ad5 -Signed-off-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - drivers/dma-buf/dma-buf.c | 14 ++++++++++++++ - include/linux/dma-buf.h | 15 +++++++++++++++ - 2 files changed, 29 insertions(+) - -diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c -index 532a854be1b3..59f6a39120fd 100644 ---- a/drivers/dma-buf/dma-buf.c -+++ b/drivers/dma-buf/dma-buf.c -@@ -1188,6 +1188,20 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) - } - EXPORT_SYMBOL_GPL(dma_buf_vunmap); - -+int dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags) -+{ -+ int ret = 0; -+ -+ if (WARN_ON(!dmabuf) || !flags) -+ return -EINVAL; -+ -+ if (dmabuf->ops->get_flags) -+ ret = dmabuf->ops->get_flags(dmabuf, flags); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(dma_buf_get_flags); -+ - #ifdef CONFIG_DEBUG_FS - static int dma_buf_debug_show(struct seq_file *s, void *unused) - { -diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h -index 0458da673ec5..f26b4a8212d0 100644 ---- a/include/linux/dma-buf.h -+++ b/include/linux/dma-buf.h -@@ -318,6 +318,20 @@ struct dma_buf_ops { - - void *(*vmap)(struct dma_buf *); - void (*vunmap)(struct dma_buf *, void *vaddr); -+ -+ /** -+ * @get_flags: -+ * -+ * This is called by dma_buf_get_flags and is used to get the buffer's -+ * flags. -+ * This callback is optional. -+ * -+ * Returns: -+ * -+ * 0 on success or a negative error code on failure. On success flags -+ * will be populated with the buffer's flags. -+ */ -+ int (*get_flags)(struct dma_buf *dmabuf, unsigned long *flags); - }; - - /** -@@ -486,4 +500,5 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *, - unsigned long); - void *dma_buf_vmap(struct dma_buf *); - void dma_buf_vunmap(struct dma_buf *, void *vaddr); -+int dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags); - #endif /* __DMA_BUF_H__ */ diff --git a/patches/ANDROID-first-pass-cuttlefish-GKI-modularization.patch b/patches/ANDROID-first-pass-cuttlefish-GKI-modularization.patch deleted file mode 100644 index 813e51f1a383bb6d3fe2f4b4fea54d46d9544dc1..0000000000000000000000000000000000000000 --- a/patches/ANDROID-first-pass-cuttlefish-GKI-modularization.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Thu, 29 Aug 2019 19:15:01 -0700 -Subject: ANDROID: first pass cuttlefish GKI modularization - -Bug: 132629930 -Signed-off-by: Ram Muthiah -Change-Id: Ie2a4d08596b0e2af7c868224bc18dcd6adae7ee0 ---- - arch/x86/configs/gki_defconfig | 28 ++++++++++++++++------------ - 1 file changed, 16 insertions(+), 12 deletions(-) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 6b0ff4ca236a..a37fa09bd107 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -155,8 +155,12 @@ CONFIG_NET_CLS_BPF=y - CONFIG_NET_EMATCH=y - CONFIG_NET_EMATCH_U32=y - CONFIG_NET_CLS_ACT=y --CONFIG_VSOCKETS=y --CONFIG_VIRTIO_VSOCKETS=y -+CONFIG_VSOCKETS=m -+CONFIG_VIRTIO_VSOCKETS=m -+CONFIG_CAN=m -+# CONFIG_CAN_BCM is not set -+# CONFIG_CAN_GW is not set -+CONFIG_CAN_VCAN=m - CONFIG_CFG80211=y - # CONFIG_CFG80211_DEFAULT_PS is not set - # CONFIG_CFG80211_CRDA_SUPPORT is not set -@@ -170,7 +174,7 @@ CONFIG_ZRAM=y - CONFIG_BLK_DEV_LOOP=y - CONFIG_BLK_DEV_RAM=y - CONFIG_BLK_DEV_RAM_SIZE=8192 --CONFIG_VIRTIO_BLK=y -+CONFIG_VIRTIO_BLK=m - CONFIG_UID_SYS_STATS=y - CONFIG_SCSI=y - # CONFIG_SCSI_PROC_FS is not set -@@ -185,7 +189,7 @@ CONFIG_DM_VERITY_FEC=y - CONFIG_DM_BOW=y - CONFIG_NETDEVICES=y - CONFIG_TUN=y --CONFIG_VIRTIO_NET=y -+CONFIG_VIRTIO_NET=m - # CONFIG_ETHERNET is not set - CONFIG_PHYLIB=y - CONFIG_PPP=y -@@ -219,7 +223,7 @@ CONFIG_USB_USBNET=y - # CONFIG_WLAN_VENDOR_TI is not set - # CONFIG_WLAN_VENDOR_ZYDAS is not set - # CONFIG_WLAN_VENDOR_QUANTENNA is not set --CONFIG_VIRT_WIFI=y -+CONFIG_VIRT_WIFI=m - CONFIG_INPUT_EVDEV=y - # CONFIG_INPUT_KEYBOARD is not set - # CONFIG_INPUT_MOUSE is not set -@@ -236,9 +240,8 @@ CONFIG_SERIAL_8250_NR_UARTS=48 - CONFIG_SERIAL_8250_EXTENDED=y - CONFIG_SERIAL_8250_MANY_PORTS=y - CONFIG_SERIAL_8250_SHARE_IRQ=y --CONFIG_VIRTIO_CONSOLE=y - CONFIG_HW_RANDOM=y --CONFIG_HW_RANDOM_VIRTIO=y -+CONFIG_HW_RANDOM_VIRTIO=m - # CONFIG_I2C_COMPAT is not set - # CONFIG_I2C_HELPER_AUTO is not set - CONFIG_SPI=y -@@ -250,7 +253,7 @@ CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set --CONFIG_DRM_VIRTIO_GPU=y -+CONFIG_DRM_VIRTIO_GPU=m - # CONFIG_LCD_CLASS_DEVICE is not set - CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_SOUND=y -@@ -260,6 +263,7 @@ CONFIG_SND_DYNAMIC_MINORS=y - # CONFIG_SND_SUPPORT_OLD_API is not set - # CONFIG_SND_VERBOSE_PROCFS is not set - # CONFIG_SND_DRIVERS is not set -+CONFIG_SND_INTEL8X0=m - # CONFIG_SND_USB is not set - CONFIG_HIDRAW=y - CONFIG_UHID=y -@@ -285,9 +289,10 @@ CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_SYSTOHC is not set --CONFIG_VIRTIO_PCI=y --CONFIG_VIRTIO_INPUT=y --CONFIG_VIRTIO_MMIO=y -+CONFIG_RTC_DRV_TEST=m -+CONFIG_VIRTIO_PCI=m -+CONFIG_VIRTIO_INPUT=m -+CONFIG_VIRTIO_MMIO=m - CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y - CONFIG_STAGING=y - CONFIG_ASHMEM=y -@@ -325,7 +330,6 @@ CONFIG_CRYPTO_SHA512=y - CONFIG_CRYPTO_LZ4=y - CONFIG_CRYPTO_ZSTD=y - CONFIG_CRYPTO_ANSI_CPRNG=y --CONFIG_CRYPTO_DEV_VIRTIO=y - CONFIG_CRC8=y - CONFIG_XZ_DEC=y - CONFIG_DMA_CMA=y diff --git a/patches/ANDROID-fix-kernelci-build-break.patch b/patches/ANDROID-fix-kernelci-build-break.patch deleted file mode 100644 index fa850a2aabbffcb08f0c612d4316154ab8b6c82f..0000000000000000000000000000000000000000 --- a/patches/ANDROID-fix-kernelci-build-break.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Tue, 20 Aug 2019 09:41:56 -0700 -Subject: ANDROID: fix kernelci build-break - -Added missing #includes to fix 'allmodconfig' builds - -Bug: 120445624 -Bug: 120445421 -Change-Id: Ia8823adf2b33aa31c6d3f9d50ca7679ef4a64eaa -Signed-off-by: Todd Kjos ---- - include/linux/netfilter/xt_quota2.h | 1 + - include/trace/events/android_fs.h | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/include/linux/netfilter/xt_quota2.h b/include/linux/netfilter/xt_quota2.h -index eadc6903314e..a3918718cbf8 100644 ---- a/include/linux/netfilter/xt_quota2.h -+++ b/include/linux/netfilter/xt_quota2.h -@@ -1,5 +1,6 @@ - #ifndef _XT_QUOTA_H - #define _XT_QUOTA_H -+#include - - enum xt_quota_flags { - XT_QUOTA_INVERT = 1 << 0, -diff --git a/include/trace/events/android_fs.h b/include/trace/events/android_fs.h -index 49509533d3fa..7edb6bcfe482 100644 ---- a/include/trace/events/android_fs.h -+++ b/include/trace/events/android_fs.h -@@ -4,6 +4,7 @@ - #if !defined(_TRACE_ANDROID_FS_H) || defined(TRACE_HEADER_MULTI_READ) - #define _TRACE_ANDROID_FS_H - -+#include - #include - #include - diff --git a/patches/ANDROID-fs-FS-tracepoints-to-track-IO.patch b/patches/ANDROID-fs-FS-tracepoints-to-track-IO.patch deleted file mode 100644 index f8f5918a298ba9fde5397a4938b06fa38704663a..0000000000000000000000000000000000000000 --- a/patches/ANDROID-fs-FS-tracepoints-to-track-IO.patch +++ /dev/null @@ -1,634 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mohan Srinivasan -Date: Wed, 14 Dec 2016 16:39:51 -0800 -Subject: ANDROID: fs: FS tracepoints to track IO. - -Adds tracepoints in ext4/f2fs/mpage to track readpages/buffered -write()s. This allows us to track files that are being read/written -to PIDs. - -Bug: 120445624 -Change-Id: I44476230324e9397e292328463f846af4befbd6d -[joelaf: Needed for storaged fsync accounting ("storaged --uid" and - "storaged --task".)] -Signed-off-by: Mohan Srinivasan -[AmitP: Folded following android-4.9 commit changes into this patch - a5c4dbb05ab7 ("ANDROID: Replace spaces by '_' for some - android filesystem tracepoints.")] -Signed-off-by: Amit Pundir -[astrachan: Folded 63066f4acf92 ("ANDROID: fs: Refactor FS - readpage/write tracepoints.") into this patch -Signed-off-by: Alistair Strachan ---- - fs/ext4/inline.c | 14 +++++ - fs/ext4/inode.c | 55 ++++++++++++++++++ - fs/ext4/readpage.c | 47 ++++++++++++++-- - fs/f2fs/data.c | 42 ++++++++++++++ - fs/f2fs/inline.c | 18 ++++++ - fs/mpage.c | 36 ++++++++++++ - include/trace/events/android_fs.h | 65 ++++++++++++++++++++++ - include/trace/events/android_fs_template.h | 64 +++++++++++++++++++++ - 8 files changed, 337 insertions(+), 4 deletions(-) - create mode 100644 include/trace/events/android_fs.h - create mode 100644 include/trace/events/android_fs_template.h - -diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c -index 2fec62d764fa..2f187da48c83 100644 ---- a/fs/ext4/inline.c -+++ b/fs/ext4/inline.c -@@ -12,6 +12,7 @@ - #include "ext4.h" - #include "xattr.h" - #include "truncate.h" -+#include - - #define EXT4_XATTR_SYSTEM_DATA "data" - #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) -@@ -505,6 +506,17 @@ int ext4_readpage_inline(struct inode *inode, struct page *page) - return -EAGAIN; - } - -+ if (trace_android_fs_dataread_start_enabled()) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_dataread_start(inode, page_offset(page), -+ PAGE_SIZE, current->pid, -+ path, current->comm); -+ } -+ - /* - * Current inline data can only exist in the 1st page, - * So for all the other pages, just set them uptodate. -@@ -516,6 +528,8 @@ int ext4_readpage_inline(struct inode *inode, struct page *page) - SetPageUptodate(page); - } - -+ trace_android_fs_dataread_end(inode, page_offset(page), PAGE_SIZE); -+ - up_read(&EXT4_I(inode)->xattr_sem); - - unlock_page(page); -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 516faa280ced..ac409eb63100 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -47,6 +47,7 @@ - #include "truncate.h" - - #include -+#include - - #define MPAGE_DA_EXTENT_TAIL 0x01 - -@@ -1269,6 +1270,16 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, - if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) - return -EIO; - -+ if (trace_android_fs_datawrite_start_enabled()) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_datawrite_start(inode, pos, len, -+ current->pid, path, -+ current->comm); -+ } - trace_ext4_write_begin(inode, pos, len, flags); - /* - * Reserve one block more for addition to orphan list in case -@@ -1411,6 +1422,7 @@ static int ext4_write_end(struct file *file, - int inline_data = ext4_has_inline_data(inode); - bool verity = ext4_verity_in_progress(inode); - -+ trace_android_fs_datawrite_end(inode, pos, len); - trace_ext4_write_end(inode, pos, len, copied); - if (inline_data) { - ret = ext4_write_inline_data_end(inode, pos, len, -@@ -1521,6 +1533,7 @@ static int ext4_journalled_write_end(struct file *file, - int inline_data = ext4_has_inline_data(inode); - bool verity = ext4_verity_in_progress(inode); - -+ trace_android_fs_datawrite_end(inode, pos, len); - trace_ext4_journalled_write_end(inode, pos, len, copied); - from = pos & (PAGE_SIZE - 1); - to = from + len; -@@ -3040,6 +3053,16 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, - len, flags, pagep, fsdata); - } - *fsdata = (void *)0; -+ if (trace_android_fs_datawrite_start_enabled()) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_datawrite_start(inode, pos, len, -+ current->pid, -+ path, current->comm); -+ } - trace_ext4_da_write_begin(inode, pos, len, flags); - - if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { -@@ -3158,6 +3181,7 @@ static int ext4_da_write_end(struct file *file, - return ext4_write_end(file, mapping, pos, - len, copied, page, fsdata); - -+ trace_android_fs_datawrite_end(inode, pos, len); - trace_ext4_da_write_end(inode, pos, len, copied); - start = pos & (PAGE_SIZE - 1); - end = start + copied - 1; -@@ -3846,6 +3870,7 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) - size_t count = iov_iter_count(iter); - loff_t offset = iocb->ki_pos; - ssize_t ret; -+ int rw = iov_iter_rw(iter); - - #ifdef CONFIG_FS_ENCRYPTION - if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) -@@ -3864,12 +3889,42 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) - if (ext4_has_inline_data(inode)) - return 0; - -+ if (trace_android_fs_dataread_start_enabled() && -+ (rw == READ)) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_dataread_start(inode, offset, count, -+ current->pid, path, -+ current->comm); -+ } -+ if (trace_android_fs_datawrite_start_enabled() && -+ (rw == WRITE)) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_datawrite_start(inode, offset, count, -+ current->pid, path, -+ current->comm); -+ } - trace_ext4_direct_IO_enter(inode, offset, count, iov_iter_rw(iter)); - if (iov_iter_rw(iter) == READ) - ret = ext4_direct_IO_read(iocb, iter); - else - ret = ext4_direct_IO_write(iocb, iter); - trace_ext4_direct_IO_exit(inode, offset, count, iov_iter_rw(iter), ret); -+ -+ if (trace_android_fs_dataread_start_enabled() && -+ (rw == READ)) -+ trace_android_fs_dataread_end(inode, offset, count); -+ if (trace_android_fs_datawrite_start_enabled() && -+ (rw == WRITE)) -+ trace_android_fs_datawrite_end(inode, offset, count); -+ - return ret; - } - -diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c -index a30b203fa461..0d88b82a5929 100644 ---- a/fs/ext4/readpage.c -+++ b/fs/ext4/readpage.c -@@ -46,6 +46,7 @@ - #include - - #include "ext4.h" -+#include - - #define NUM_PREALLOC_POST_READ_CTXS 128 - -@@ -146,6 +147,17 @@ static bool bio_post_read_required(struct bio *bio) - return bio->bi_private && !bio->bi_status; - } - -+static void -+ext4_trace_read_completion(struct bio *bio) -+{ -+ struct page *first_page = bio->bi_io_vec[0].bv_page; -+ -+ if (first_page != NULL) -+ trace_android_fs_dataread_end(first_page->mapping->host, -+ page_offset(first_page), -+ bio->bi_iter.bi_size); -+} -+ - /* - * I/O completion handler for multipage BIOs. - * -@@ -160,6 +172,9 @@ static bool bio_post_read_required(struct bio *bio) - */ - static void mpage_end_io(struct bio *bio) - { -+ if (trace_android_fs_dataread_start_enabled()) -+ ext4_trace_read_completion(bio); -+ - if (bio_post_read_required(bio)) { - struct bio_post_read_ctx *ctx = bio->bi_private; - -@@ -209,6 +224,30 @@ static inline loff_t ext4_readpage_limit(struct inode *inode) - return i_size_read(inode); - } - -+static void -+ext4_submit_bio_read(struct bio *bio) -+{ -+ if (trace_android_fs_dataread_start_enabled()) { -+ struct page *first_page = bio->bi_io_vec[0].bv_page; -+ -+ if (first_page != NULL) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ first_page->mapping->host); -+ trace_android_fs_dataread_start( -+ first_page->mapping->host, -+ page_offset(first_page), -+ bio->bi_iter.bi_size, -+ current->pid, -+ path, -+ current->comm); -+ } -+ } -+ submit_bio(bio); -+} -+ - int ext4_mpage_readpages(struct address_space *mapping, - struct list_head *pages, struct page *page, - unsigned nr_pages, bool is_readahead) -@@ -354,7 +393,7 @@ int ext4_mpage_readpages(struct address_space *mapping, - */ - if (bio && (last_block_in_bio != blocks[0] - 1)) { - submit_and_realloc: -- submit_bio(bio); -+ ext4_submit_bio_read(bio); - bio = NULL; - } - if (bio == NULL) { -@@ -385,14 +424,14 @@ int ext4_mpage_readpages(struct address_space *mapping, - if (((map.m_flags & EXT4_MAP_BOUNDARY) && - (relative_block == map.m_len)) || - (first_hole != blocks_per_page)) { -- submit_bio(bio); -+ ext4_submit_bio_read(bio); - bio = NULL; - } else - last_block_in_bio = blocks[blocks_per_page - 1]; - goto next_page; - confused: - if (bio) { -- submit_bio(bio); -+ ext4_submit_bio_read(bio); - bio = NULL; - } - if (!PageUptodate(page)) -@@ -405,7 +444,7 @@ int ext4_mpage_readpages(struct address_space *mapping, - } - BUG_ON(pages && !list_empty(pages)); - if (bio) -- submit_bio(bio); -+ ext4_submit_bio_read(bio); - return 0; - } - -diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c -index 5755e897a5f0..9155256779bf 100644 ---- a/fs/f2fs/data.c -+++ b/fs/f2fs/data.c -@@ -25,6 +25,7 @@ - #include "segment.h" - #include "trace.h" - #include -+#include - - #define NUM_PREALLOC_POST_READ_CTXS 128 - -@@ -2623,6 +2624,16 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, - block_t blkaddr = NULL_ADDR; - int err = 0; - -+ if (trace_android_fs_datawrite_start_enabled()) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_datawrite_start(inode, pos, len, -+ current->pid, path, -+ current->comm); -+ } - trace_f2fs_write_begin(inode, pos, len, flags); - - if (!f2fs_is_checkpoint_ready(sbi)) { -@@ -2730,6 +2741,7 @@ static int f2fs_write_end(struct file *file, - { - struct inode *inode = page->mapping->host; - -+ trace_android_fs_datawrite_end(inode, pos, len); - trace_f2fs_write_end(inode, pos, len, copied); - - /* -@@ -2846,6 +2858,29 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) - - trace_f2fs_direct_IO_enter(inode, offset, count, rw); - -+ if (trace_android_fs_dataread_start_enabled() && -+ (rw == READ)) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_dataread_start(inode, offset, -+ count, current->pid, path, -+ current->comm); -+ } -+ if (trace_android_fs_datawrite_start_enabled() && -+ (rw == WRITE)) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_datawrite_start(inode, offset, count, -+ current->pid, path, -+ current->comm); -+ } -+ - if (rw == WRITE && whint_mode == WHINT_MODE_OFF) - iocb->ki_hint = WRITE_LIFE_NOT_SET; - -@@ -2891,6 +2926,13 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) - } - - out: -+ if (trace_android_fs_dataread_start_enabled() && -+ (rw == READ)) -+ trace_android_fs_dataread_end(inode, offset, count); -+ if (trace_android_fs_datawrite_start_enabled() && -+ (rw == WRITE)) -+ trace_android_fs_datawrite_end(inode, offset, count); -+ - trace_f2fs_direct_IO_exit(inode, offset, count, rw, err); - - return err; -diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c -index 896db0416f0e..59adbfa25bac 100644 ---- a/fs/f2fs/inline.c -+++ b/fs/f2fs/inline.c -@@ -11,6 +11,7 @@ - - #include "f2fs.h" - #include "node.h" -+#include - - bool f2fs_may_inline_data(struct inode *inode) - { -@@ -84,14 +85,29 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page) - { - struct page *ipage; - -+ if (trace_android_fs_dataread_start_enabled()) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ inode); -+ trace_android_fs_dataread_start(inode, page_offset(page), -+ PAGE_SIZE, current->pid, -+ path, current->comm); -+ } -+ - ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); - if (IS_ERR(ipage)) { -+ trace_android_fs_dataread_end(inode, page_offset(page), -+ PAGE_SIZE); - unlock_page(page); - return PTR_ERR(ipage); - } - - if (!f2fs_has_inline_data(inode)) { - f2fs_put_page(ipage, 1); -+ trace_android_fs_dataread_end(inode, page_offset(page), -+ PAGE_SIZE); - return -EAGAIN; - } - -@@ -103,6 +119,8 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page) - if (!PageUptodate(page)) - SetPageUptodate(page); - f2fs_put_page(ipage, 1); -+ trace_android_fs_dataread_end(inode, page_offset(page), -+ PAGE_SIZE); - unlock_page(page); - return 0; - } -diff --git a/fs/mpage.c b/fs/mpage.c -index a63620cdb73a..e8281998e690 100644 ---- a/fs/mpage.c -+++ b/fs/mpage.c -@@ -32,6 +32,14 @@ - #include - #include "internal.h" - -+#define CREATE_TRACE_POINTS -+#include -+ -+EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_start); -+EXPORT_TRACEPOINT_SYMBOL(android_fs_datawrite_end); -+EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_start); -+EXPORT_TRACEPOINT_SYMBOL(android_fs_dataread_end); -+ - /* - * I/O completion handler for multipage BIOs. - * -@@ -49,6 +57,16 @@ static void mpage_end_io(struct bio *bio) - struct bio_vec *bv; - struct bvec_iter_all iter_all; - -+ if (trace_android_fs_dataread_end_enabled() && -+ (bio_data_dir(bio) == READ)) { -+ struct page *first_page = bio->bi_io_vec[0].bv_page; -+ -+ if (first_page != NULL) -+ trace_android_fs_dataread_end(first_page->mapping->host, -+ page_offset(first_page), -+ bio->bi_iter.bi_size); -+ } -+ - bio_for_each_segment_all(bv, bio, iter_all) { - struct page *page = bv->bv_page; - page_endio(page, bio_op(bio), -@@ -60,6 +78,24 @@ static void mpage_end_io(struct bio *bio) - - static struct bio *mpage_bio_submit(int op, int op_flags, struct bio *bio) - { -+ if (trace_android_fs_dataread_start_enabled() && (op == REQ_OP_READ)) { -+ struct page *first_page = bio->bi_io_vec[0].bv_page; -+ -+ if (first_page != NULL) { -+ char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; -+ -+ path = android_fstrace_get_pathname(pathbuf, -+ MAX_TRACE_PATHBUF_LEN, -+ first_page->mapping->host); -+ trace_android_fs_dataread_start( -+ first_page->mapping->host, -+ page_offset(first_page), -+ bio->bi_iter.bi_size, -+ current->pid, -+ path, -+ current->comm); -+ } -+ } - bio->bi_end_io = mpage_end_io; - bio_set_op_attrs(bio, op, op_flags); - guard_bio_eod(op, bio); -diff --git a/include/trace/events/android_fs.h b/include/trace/events/android_fs.h -new file mode 100644 -index 000000000000..49509533d3fa ---- /dev/null -+++ b/include/trace/events/android_fs.h -@@ -0,0 +1,65 @@ -+#undef TRACE_SYSTEM -+#define TRACE_SYSTEM android_fs -+ -+#if !defined(_TRACE_ANDROID_FS_H) || defined(TRACE_HEADER_MULTI_READ) -+#define _TRACE_ANDROID_FS_H -+ -+#include -+#include -+ -+DEFINE_EVENT(android_fs_data_start_template, android_fs_dataread_start, -+ TP_PROTO(struct inode *inode, loff_t offset, int bytes, -+ pid_t pid, char *pathname, char *command), -+ TP_ARGS(inode, offset, bytes, pid, pathname, command)); -+ -+DEFINE_EVENT(android_fs_data_end_template, android_fs_dataread_end, -+ TP_PROTO(struct inode *inode, loff_t offset, int bytes), -+ TP_ARGS(inode, offset, bytes)); -+ -+DEFINE_EVENT(android_fs_data_start_template, android_fs_datawrite_start, -+ TP_PROTO(struct inode *inode, loff_t offset, int bytes, -+ pid_t pid, char *pathname, char *command), -+ TP_ARGS(inode, offset, bytes, pid, pathname, command)); -+ -+DEFINE_EVENT(android_fs_data_end_template, android_fs_datawrite_end, -+ TP_PROTO(struct inode *inode, loff_t offset, int bytes), -+ TP_ARGS(inode, offset, bytes)); -+ -+#endif /* _TRACE_ANDROID_FS_H */ -+ -+/* This part must be outside protection */ -+#include -+ -+#ifndef ANDROID_FSTRACE_GET_PATHNAME -+#define ANDROID_FSTRACE_GET_PATHNAME -+ -+/* Sizes an on-stack array, so careful if sizing this up ! */ -+#define MAX_TRACE_PATHBUF_LEN 256 -+ -+static inline char * -+android_fstrace_get_pathname(char *buf, int buflen, struct inode *inode) -+{ -+ char *path; -+ struct dentry *d; -+ -+ /* -+ * d_obtain_alias() will either iput() if it locates an existing -+ * dentry or transfer the reference to the new dentry created. -+ * So get an extra reference here. -+ */ -+ ihold(inode); -+ d = d_obtain_alias(inode); -+ if (likely(!IS_ERR(d))) { -+ path = dentry_path_raw(d, buf, buflen); -+ if (unlikely(IS_ERR(path))) { -+ strcpy(buf, "ERROR"); -+ path = buf; -+ } -+ dput(d); -+ } else { -+ strcpy(buf, "ERROR"); -+ path = buf; -+ } -+ return path; -+} -+#endif -diff --git a/include/trace/events/android_fs_template.h b/include/trace/events/android_fs_template.h -new file mode 100644 -index 000000000000..b23d17b56c63 ---- /dev/null -+++ b/include/trace/events/android_fs_template.h -@@ -0,0 +1,64 @@ -+#if !defined(_TRACE_ANDROID_FS_TEMPLATE_H) || defined(TRACE_HEADER_MULTI_READ) -+#define _TRACE_ANDROID_FS_TEMPLATE_H -+ -+#include -+ -+DECLARE_EVENT_CLASS(android_fs_data_start_template, -+ TP_PROTO(struct inode *inode, loff_t offset, int bytes, -+ pid_t pid, char *pathname, char *command), -+ TP_ARGS(inode, offset, bytes, pid, pathname, command), -+ TP_STRUCT__entry( -+ __string(pathbuf, pathname); -+ __field(loff_t, offset); -+ __field(int, bytes); -+ __field(loff_t, i_size); -+ __string(cmdline, command); -+ __field(pid_t, pid); -+ __field(ino_t, ino); -+ ), -+ TP_fast_assign( -+ { -+ /* -+ * Replace the spaces in filenames and cmdlines -+ * because this screws up the tooling that parses -+ * the traces. -+ */ -+ __assign_str(pathbuf, pathname); -+ (void)strreplace(__get_str(pathbuf), ' ', '_'); -+ __entry->offset = offset; -+ __entry->bytes = bytes; -+ __entry->i_size = i_size_read(inode); -+ __assign_str(cmdline, command); -+ (void)strreplace(__get_str(cmdline), ' ', '_'); -+ __entry->pid = pid; -+ __entry->ino = inode->i_ino; -+ } -+ ), -+ TP_printk("entry_name %s, offset %llu, bytes %d, cmdline %s," -+ " pid %d, i_size %llu, ino %lu", -+ __get_str(pathbuf), __entry->offset, __entry->bytes, -+ __get_str(cmdline), __entry->pid, __entry->i_size, -+ (unsigned long) __entry->ino) -+); -+ -+DECLARE_EVENT_CLASS(android_fs_data_end_template, -+ TP_PROTO(struct inode *inode, loff_t offset, int bytes), -+ TP_ARGS(inode, offset, bytes), -+ TP_STRUCT__entry( -+ __field(ino_t, ino); -+ __field(loff_t, offset); -+ __field(int, bytes); -+ ), -+ TP_fast_assign( -+ { -+ __entry->ino = inode->i_ino; -+ __entry->offset = offset; -+ __entry->bytes = bytes; -+ } -+ ), -+ TP_printk("ino %lu, offset %llu, bytes %d", -+ (unsigned long) __entry->ino, -+ __entry->offset, __entry->bytes) -+); -+ -+#endif /* _TRACE_ANDROID_FS_TEMPLATE_H */ diff --git a/patches/ANDROID-fs-Restore-vfs_path_lookup-export.patch b/patches/ANDROID-fs-Restore-vfs_path_lookup-export.patch deleted file mode 100644 index 2cd56a0634b3b6b9fcd112a84280f7a17a18bfd3..0000000000000000000000000000000000000000 --- a/patches/ANDROID-fs-Restore-vfs_path_lookup-export.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Strachan -Date: Mon, 19 Nov 2018 22:38:23 -0800 -Subject: ANDROID: fs: Restore vfs_path_lookup() export - -Partial revert of 197df04c749a ("rename user_path_umountat() to -user_path_mountpoint_at()"), to restore access to vfs_path_lookup() -without including fs/internal.h, as needed by sdcardfs. - -Test: HiKey/X15 + Pie + android-mainline, - and HiKey + AOSP Maser + android-mainline, - directories under /sdcard created, - output of mount is right, - CTS test collecting device infor works - -Change-Id: I757f2df9f4dcc66f633939e7833e6fa2ac0ff4f8 -Signed-off-by: Alistair Strachan -Signed-off-by: Yongqin Liu ---- - fs/internal.h | 2 -- - include/linux/namei.h | 2 ++ - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/fs/internal.h b/fs/internal.h -index 315fcd8d237c..df6e4c4584f3 100644 ---- a/fs/internal.h -+++ b/fs/internal.h -@@ -62,8 +62,6 @@ extern int finish_clean_context(struct fs_context *fc); - extern int filename_lookup(int dfd, struct filename *name, unsigned flags, - struct path *path, struct path *root); - extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *); --extern int vfs_path_lookup(struct dentry *, struct vfsmount *, -- const char *, unsigned int, struct path *); - long do_mknodat(int dfd, const char __user *filename, umode_t mode, - unsigned int dev); - long do_mkdirat(int dfd, const char __user *pathname, umode_t mode); -diff --git a/include/linux/namei.h b/include/linux/namei.h -index cb288d62f1d6..5f04b40747b2 100644 ---- a/include/linux/namei.h -+++ b/include/linux/namei.h -@@ -55,6 +55,8 @@ extern struct dentry *kern_path_create(int, const char *, struct path *, unsigne - extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int); - extern void done_path_create(struct path *, struct dentry *); - extern struct dentry *kern_path_locked(const char *, struct path *); -+extern int vfs_path_lookup(struct dentry *, struct vfsmount *, -+ const char *, unsigned int, struct path *); - extern int kern_path_mountpoint(int, const char *, struct path *, unsigned int); - - extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int); diff --git a/patches/ANDROID-fs-epoll-use-freezable-blocking-call.patch b/patches/ANDROID-fs-epoll-use-freezable-blocking-call.patch deleted file mode 100644 index 3fe2cf9bc7e7f4dcdd0586a964a449387ddae82d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-fs-epoll-use-freezable-blocking-call.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Colin Cross -Date: Mon, 6 May 2013 23:50:16 +0000 -Subject: ANDROID: fs: epoll: use freezable blocking call - -Avoid waking up every thread sleeping in an epoll_wait call during -suspend and resume by calling a freezable blocking call. Previous -patches modified the freezer to avoid sending wakeups to threads -that are blocked in freezable blocking calls. - -This call was selected to be converted to a freezable call because -it doesn't hold any locks or release any resources when interrupted -that might be needed by another freezing task or a kernel driver -during suspend, and is a common site where idle userspace tasks are -blocked. - -Bug: 77139736 -Bug: 120440023 -Change-Id: I848d08d28c89302fd42bbbdfa76489a474ab27bf -[ccross: This was upstream (https://lkml.org/lkml/2013/5/6/823), but - reverted because it reportedly caused memory corruption on - 32-bit x86 (https://patchwork.kernel.org/patch/3162301/).] -Acked-by: Tejun Heo -Signed-off-by: Colin Cross -Signed-off-by: Rafael J. Wysocki ---- - fs/eventpoll.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index c4159bcc05d9..6730d92e225a 100644 ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1912,7 +1913,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, - break; - } - -- if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) { -+ if (!freezable_schedule_hrtimeout_range(to, slack, -+ HRTIMER_MODE_ABS)) { - timed_out = 1; - break; - } diff --git a/patches/ANDROID-gki-cuttlefish-defconfigs-use-prebuilt-build-tools.patch b/patches/ANDROID-gki-cuttlefish-defconfigs-use-prebuilt-build-tools.patch deleted file mode 100644 index 8e210a466e7bc74c1dc46692517e3e209460c4a3..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki-cuttlefish-defconfigs-use-prebuilt-build-tools.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthias Maennich -Date: Mon, 24 Jun 2019 18:10:19 +0100 -Subject: ANDROID: gki/cuttlefish defconfigs: use prebuilt build-tools - -Rather than relying on the hosts build tools, use a set of prebuilt -build-tools. These are tools like awk, cat, cp, hostname, python, rm, -sed, etc. - -Bug: 135922132 -Change-Id: Ie6b0bd208c684c9f153eb2f0bfac4712e02e8e05 -Signed-off-by: Matthias Maennich ---- - build.config.gki.aarch64 | 1 + - build.config.gki.x86_64 | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 -index ecc2985e92cb..24dade721f96 100644 ---- a/build.config.gki.aarch64 -+++ b/build.config.gki.aarch64 -@@ -8,6 +8,7 @@ EXTRA_CMDS='' - KERNEL_DIR=common - POST_DEFCONFIG_CMDS="check_defconfig" - CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin -+BUILDTOOLS_PREBUILT_BIN=prebuilts/build-tools/path/linux-x86 - LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin - FILES=" - arch/arm64/boot/Image.gz -diff --git a/build.config.gki.x86_64 b/build.config.gki.x86_64 -index 69d339dce4a0..3ce45e962732 100644 ---- a/build.config.gki.x86_64 -+++ b/build.config.gki.x86_64 -@@ -8,6 +8,7 @@ EXTRA_CMDS='' - KERNEL_DIR=common - POST_DEFCONFIG_CMDS="check_defconfig" - CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin -+BUILDTOOLS_PREBUILT_BIN=prebuilts/build-tools/path/linux-x86 - LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin - FILES=" - arch/x86/boot/bzImage diff --git a/patches/ANDROID-gki_defconfig-Add-GKI_HACKS_to_FIX-config.patch b/patches/ANDROID-gki_defconfig-Add-GKI_HACKS_to_FIX-config.patch deleted file mode 100644 index c852c93fbf3f9b6726c9d34c2f8869ab1a4c2402..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Add-GKI_HACKS_to_FIX-config.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Tue, 17 Sep 2019 16:22:18 -0700 -Subject: ANDROID: gki_defconfig: Add GKI_HACKS_to_FIX config - -Enable config which selects a number of non-module -options which are usually selected by drivers built -as modules - -Bug: 141266428 -Change-Id: I8d95c96b74b2cfd861d68573135455a3392ff522 -Signed-off-by: Todd Kjos ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index f65b544d17a4..8edcded9ab1f 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -72,6 +72,7 @@ CONFIG_KPROBES=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y -+CONFIG_GKI_HACKS_TO_FIX=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set - CONFIG_MEMORY_HOTPLUG=y - CONFIG_TRANSPARENT_HUGEPAGE=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 3e8f580e0bde..bf0ab5abf5e7 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -47,6 +47,7 @@ CONFIG_KPROBES=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y -+CONFIG_GKI_HACKS_TO_FIX=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set - CONFIG_TRANSPARENT_HUGEPAGE=y - CONFIG_CMA=y diff --git a/patches/ANDROID-gki_defconfig-Enable-BPF_JIT-and-BPF_JIT_ALWAYS_ON.patch b/patches/ANDROID-gki_defconfig-Enable-BPF_JIT-and-BPF_JIT_ALWAYS_ON.patch deleted file mode 100644 index 6cf2a2f474cf13ad3dcf8cc25514f8f5866b6802..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Enable-BPF_JIT-and-BPF_JIT_ALWAYS_ON.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= -Date: Tue, 8 Oct 2019 08:51:00 -0700 -Subject: ANDROID: gki_defconfig: Enable BPF_JIT and BPF_JIT_ALWAYS_ON -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Generated via: - echo 'CONFIG_BPF_JIT=y' >> arch/x86/configs/gki_defconfig - echo 'CONFIG_BPF_JIT_ALWAYS_ON=y' >> arch/x86/configs/gki_defconfig - - make ARCH=x86_64 gki_defconfig - make ARCH=x86_64 savedefconfig - mv defconfig arch/x86/configs/gki_defconfig - - echo 'CONFIG_BPF_JIT=y' >> arch/arm64/configs/gki_defconfig - echo 'CONFIG_BPF_JIT_ALWAYS_ON=y' >> arch/arm64/configs/gki_defconfig - - make ARCH=arm64 gki_defconfig - make ARCH=arm64 savedefconfig - mv defconfig arch/arm64/configs/gki_defconfig - -Bug: 140377409 -Signed-off-by: Maciej Żenczykowski -Change-Id: I84e917b75ca2cbe4d4b61c0d042f9fbcf5bdf519 ---- - arch/arm64/configs/gki_defconfig | 2 ++ - arch/x86/configs/gki_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 97e0e47767e2..9e3b34fa8b64 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -28,6 +28,7 @@ CONFIG_BLK_DEV_INITRD=y - # CONFIG_FHANDLE is not set - CONFIG_KALLSYMS_ALL=y - CONFIG_BPF_SYSCALL=y -+CONFIG_BPF_JIT_ALWAYS_ON=y - # CONFIG_RSEQ is not set - CONFIG_EMBEDDED=y - # CONFIG_VM_EVENT_COUNTERS is not set -@@ -187,6 +188,7 @@ CONFIG_NET_EMATCH_U32=y - CONFIG_NET_CLS_ACT=y - CONFIG_VSOCKETS=y - CONFIG_VIRTIO_VSOCKETS=y -+CONFIG_BPF_JIT=y - CONFIG_BT=y - CONFIG_CFG80211=y - # CONFIG_CFG80211_DEFAULT_PS is not set -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 7890c249bca9..f539970bf631 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -27,6 +27,7 @@ CONFIG_BLK_DEV_INITRD=y - # CONFIG_FHANDLE is not set - CONFIG_KALLSYMS_ALL=y - CONFIG_BPF_SYSCALL=y -+CONFIG_BPF_JIT_ALWAYS_ON=y - # CONFIG_RSEQ is not set - CONFIG_EMBEDDED=y - # CONFIG_VM_EVENT_COUNTERS is not set -@@ -159,6 +160,7 @@ CONFIG_NET_EMATCH_U32=y - CONFIG_NET_CLS_ACT=y - CONFIG_VSOCKETS=m - CONFIG_VIRTIO_VSOCKETS=m -+CONFIG_BPF_JIT=y - CONFIG_CAN=m - # CONFIG_CAN_BCM is not set - # CONFIG_CAN_GW is not set diff --git a/patches/ANDROID-gki_defconfig-Enable-CMA-SLAB_FREELIST-RANDOM-and-HARDENED-on-x86.patch b/patches/ANDROID-gki_defconfig-Enable-CMA-SLAB_FREELIST-RANDOM-and-HARDENED-on-x86.patch deleted file mode 100644 index 143a83783cdeb31d4a8f38c89c1562150d58cc9d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Enable-CMA-SLAB_FREELIST-RANDOM-and-HARDENED-on-x86.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Mon, 3 Jun 2019 13:53:01 -0700 -Subject: ANDROID: gki_defconfig: Enable CMA, SLAB_FREELIST (RANDOM and - HARDENED) on x86 - -Fixes: 134087016 -Fixes: 134378085 -Test: Boot x86 cuttlefish -Change-Id: I64f9714bbda558056c47f09a5e768d7eb83e2640 -Signed-off-by: Ram Muthiah ---- - arch/x86/configs/gki_defconfig | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index cdaba53b7bb0..864595c719e7 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -30,6 +30,8 @@ CONFIG_EMBEDDED=y - # CONFIG_VM_EVENT_COUNTERS is not set - # CONFIG_COMPAT_BRK is not set - # CONFIG_SLAB_MERGE_DEFAULT is not set -+CONFIG_SLAB_FREELIST_RANDOM=y -+CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 -@@ -46,6 +48,8 @@ CONFIG_MODVERSIONS=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set - # CONFIG_SPARSEMEM_VMEMMAP is not set - CONFIG_TRANSPARENT_HUGEPAGE=y -+CONFIG_CMA=y -+CONFIG_CMA_AREAS=16 - CONFIG_ZSMALLOC=y - CONFIG_NET=y - CONFIG_PACKET=y diff --git a/patches/ANDROID-gki_defconfig-Enable-CONFIG_DM_SNAPSHOT.patch b/patches/ANDROID-gki_defconfig-Enable-CONFIG_DM_SNAPSHOT.patch deleted file mode 100644 index b16aacf1a6a943af41139f1854632a47a9dcda7d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Enable-CONFIG_DM_SNAPSHOT.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alessio Balsini -Date: Fri, 11 Oct 2019 13:50:20 +0100 -Subject: ANDROID: gki_defconfig: Enable CONFIG_DM_SNAPSHOT - -The snapshot dm target is required to implement the Virtual-AB -mechanism. -Introduce CONFIG_DM_SNAPSHOT in arm64 and x86 gki defconfigs to -enable this feature. - -Bug: 142527064 -Test: kernel build -Signed-off-by: Alessio Balsini -Change-Id: I69bc614509eaff259a2aa9195e7e1d406b36bbb2 ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 6ccf6c7ef9ec..ed21a0d79f4c 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -216,6 +216,7 @@ CONFIG_SCSI_UFSHCD_PLATFORM=y - CONFIG_MD=y - CONFIG_BLK_DEV_DM=y - CONFIG_DM_CRYPT=y -+CONFIG_DM_SNAPSHOT=y - CONFIG_DM_UEVENT=y - CONFIG_DM_VERITY=y - CONFIG_DM_VERITY_AVB=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 931fcbdced69..fbcf73e4f66f 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -189,6 +189,7 @@ CONFIG_BLK_DEV_SD=y - CONFIG_MD=y - CONFIG_BLK_DEV_DM=y - CONFIG_DM_CRYPT=y -+CONFIG_DM_SNAPSHOT=y - CONFIG_DM_UEVENT=y - CONFIG_DM_VERITY=y - CONFIG_DM_VERITY_AVB=y diff --git a/patches/ANDROID-gki_defconfig-Enable-HiSilicon-SoCs.patch b/patches/ANDROID-gki_defconfig-Enable-HiSilicon-SoCs.patch deleted file mode 100644 index c8b5484b925233ca17a42708be06c6dc3690adea..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Enable-HiSilicon-SoCs.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Wed, 18 Sep 2019 10:49:45 -0700 -Subject: ANDROID: gki_defconfig: Enable HiSilicon SoCs - -Enable configs required for HiSilicon SoCs. - -Bug: 141265942 -Change-Id: Iedb2b795bda690bdec4db3265dc391f7837208e0 -Signed-off-by: Todd Kjos ---- - arch/arm64/configs/gki_defconfig | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 1263dc50f970..f964b81a1e4b 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -36,6 +36,7 @@ CONFIG_EMBEDDED=y - CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y -+CONFIG_ARCH_HISI=y - CONFIG_ARCH_QCOM=y - CONFIG_SCHED_MC=y - CONFIG_NR_CPUS=32 -@@ -195,6 +196,7 @@ CONFIG_MAC80211=y - CONFIG_RFKILL=y - CONFIG_PCI=y - CONFIG_PCI_HOST_GENERIC=y -+CONFIG_PCIE_KIRIN=y - # CONFIG_ALLOW_DEV_COREDUMP is not set - CONFIG_DEBUG_DEVRES=y - CONFIG_ZRAM=y -@@ -280,6 +282,7 @@ CONFIG_SPI=y - CONFIG_SPMI=y - CONFIG_PINCTRL_AMD=y - CONFIG_POWER_AVS=y -+CONFIG_POWER_RESET_HISI=y - # CONFIG_HWMON is not set - CONFIG_THERMAL=y - CONFIG_THERMAL_GOV_USER_SPACE=y diff --git a/patches/ANDROID-gki_defconfig-Enable-SERIAL_DEV_BUS.patch b/patches/ANDROID-gki_defconfig-Enable-SERIAL_DEV_BUS.patch deleted file mode 100644 index e152de9afbc79fc64ed7e6de5299dbad5f5a9c57..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Enable-SERIAL_DEV_BUS.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Tue, 17 Sep 2019 16:25:46 -0700 -Subject: ANDROID: gki_defconfig: Enable SERIAL_DEV_BUS - -Enable CONFIG_SERIAL_DEV_BUS for hikey/db845c - -Bug: 141265942 -Change-Id: Iedc0d96ed10011ca0b5bedd7384f5158f32c6c76 -Signed-off-by: Todd Kjos ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 8edcded9ab1f..1263dc50f970 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -268,6 +268,7 @@ CONFIG_SERIAL_8250_CONSOLE=y - CONFIG_SERIAL_OF_PLATFORM=m - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_SERIAL_DEV_BUS=y - CONFIG_VIRTIO_CONSOLE=y - CONFIG_HW_RANDOM=y - CONFIG_HW_RANDOM_VIRTIO=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index bf0ab5abf5e7..bcd12981dff4 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -239,6 +239,7 @@ CONFIG_SERIAL_8250=y - # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set - CONFIG_SERIAL_8250_CONSOLE=y - CONFIG_SERIAL_OF_PLATFORM=m -+CONFIG_SERIAL_DEV_BUS=y - CONFIG_HW_RANDOM=y - CONFIG_HW_RANDOM_VIRTIO=m - # CONFIG_I2C_COMPAT is not set diff --git a/patches/ANDROID-gki_defconfig-Minimally-enable-EFI.patch b/patches/ANDROID-gki_defconfig-Minimally-enable-EFI.patch deleted file mode 100644 index 44c5ec72049619f93499f31f6f15f67ba73e16bb..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Minimally-enable-EFI.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: John Stultz -Date: Fri, 16 Aug 2019 22:33:20 +0000 -Subject: ANDROID: gki_defconfig: Minimally enable EFI - -HiKey/HiKey960 need UEFI support to boot but don't need much of -the other options that default on when enabling EFI. - -Bug: 140204135 -Signed-off-by: John Stultz -Change-Id: I5c2e63701ae93277fcc3ddb36a39637237c65194 ---- - arch/arm64/configs/gki_defconfig | 4 +++- - arch/x86/configs/gki_defconfig | 2 ++ - 2 files changed, 5 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 2773a84fd939..006692f065d4 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -46,7 +46,7 @@ CONFIG_SWP_EMULATION=y - CONFIG_CP15_BARRIER_EMULATION=y - CONFIG_SETEND_EMULATION=y - CONFIG_RANDOMIZE_BASE=y --# CONFIG_EFI is not set -+# CONFIG_DMI is not set - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set -@@ -64,6 +64,7 @@ CONFIG_ARM_SCMI_PROTOCOL=y - # CONFIG_ARM_SCMI_POWER_DOMAIN is not set - CONFIG_ARM_SCPI_PROTOCOL=y - # CONFIG_ARM_SCPI_POWER_DOMAIN is not set -+# CONFIG_EFI_ARMSTUB_DTB_LOADER is not set - CONFIG_ARM64_CRYPTO=y - CONFIG_CRYPTO_AES_ARM64=y - CONFIG_KPROBES=y -@@ -382,6 +383,7 @@ CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y -+# CONFIG_EFIVAR_FS is not set - CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index a1b2121bde8b..ed8296e953ed 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -36,6 +36,7 @@ CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y - CONFIG_SMP=y - CONFIG_NR_CPUS=32 -+CONFIG_EFI=y - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set -@@ -308,6 +309,7 @@ CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y -+# CONFIG_EFIVAR_FS is not set - CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y diff --git a/patches/ANDROID-gki_defconfig-Remove-cuttlefish-specific-configs.patch b/patches/ANDROID-gki_defconfig-Remove-cuttlefish-specific-configs.patch deleted file mode 100644 index d518202e98dcb3caf6d15e11ea28f96c46bb2718..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Remove-cuttlefish-specific-configs.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Fri, 10 May 2019 14:33:29 -0700 -Subject: ANDROID: gki_defconfig: Remove cuttlefish-specific configs - -Left enabled: -- configs for virtualization CONFIG_PARAVIRT, CONFIG_VIRTIO_*, etc. -- cuttlefish doesn't boot without CONFIG_KSM, CONFIG_SGETMASK_SYSCALL, - CONFIG_SCHED_AUTOGROUP - -A number of config should be modules, but due to lack of module support -in userspace are left built in: -- CONFIG_PCI_HOST_GENERIC -- CONFIG_SERIAL_* -- CONFIG_MAC80211 -- CONFIG_SND_INTEL8X0 -- CONFIG_RTC_DRV_PL030 -- CONFIG_RTC_DRV_PL031 -- CONFIG_CRYPTO_ADIANTUM -- CONFIG_CRYPTO_ZSTD - -Test: boot cuttlefish on arm64 -Signed-off-by: Tri Vo -(partially cherry picked from commit a651d6eccc912ea60d8b79ddeec23ffb1f85b65f) ---- - arch/arm64/configs/gki_defconfig | 12 ------------ - 1 file changed, 12 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index a747e222db8e..41a892ca324d 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -34,7 +34,6 @@ CONFIG_EMBEDDED=y - # CONFIG_SLAB_MERGE_DEFAULT is not set - CONFIG_PROFILING=y - CONFIG_SCHED_MC=y --CONFIG_HZ_100=y - CONFIG_SECCOMP=y - CONFIG_PARAVIRT=y - CONFIG_ARMV8_DEPRECATED=y -@@ -56,7 +55,6 @@ CONFIG_CPU_FREQ_TIMES=y - CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y - CONFIG_CPU_FREQ_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y --CONFIG_CPUFREQ_DT=y - CONFIG_ARM_SCPI_CPUFREQ=y - CONFIG_ARM_SCMI_CPUFREQ=y - CONFIG_ARM_SCMI_PROTOCOL=y -@@ -90,10 +88,6 @@ CONFIG_INET_ESP=y - # CONFIG_INET_XFRM_MODE_BEET is not set - CONFIG_INET_UDP_DIAG=y - CONFIG_INET_DIAG_DESTROY=y --CONFIG_TCP_CONG_ADVANCED=y --# CONFIG_TCP_CONG_BIC is not set --# CONFIG_TCP_CONG_WESTWOOD is not set --# CONFIG_TCP_CONG_HTCP is not set - CONFIG_IPV6_ROUTER_PREF=y - CONFIG_IPV6_ROUTE_INFO=y - CONFIG_IPV6_OPTIMISTIC_DAD=y -@@ -191,10 +185,8 @@ CONFIG_RFKILL=y - CONFIG_PCI=y - CONFIG_PCI_HOST_GENERIC=y - # CONFIG_UEVENT_HELPER is not set --CONFIG_DEVTMPFS=y - # CONFIG_ALLOW_DEV_COREDUMP is not set - CONFIG_DEBUG_DEVRES=y --CONFIG_OF_UNITTEST=y - CONFIG_ZRAM=y - CONFIG_BLK_DEV_LOOP=y - CONFIG_BLK_DEV_RAM=y -@@ -214,8 +206,6 @@ CONFIG_DM_VERITY_AVB=y - CONFIG_DM_VERITY_FEC=y - CONFIG_DM_BOW=y - CONFIG_NETDEVICES=y --CONFIG_NETCONSOLE=y --CONFIG_NETCONSOLE_DYNAMIC=y - CONFIG_TUN=y - CONFIG_VIRTIO_NET=y - # CONFIG_ETHERNET is not set -@@ -366,7 +356,6 @@ CONFIG_XZ_DEC=y - CONFIG_PRINTK_TIME=y - CONFIG_DEBUG_INFO=y - # CONFIG_ENABLE_MUST_CHECK is not set --CONFIG_FRAME_WARN=1024 - # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set - CONFIG_MAGIC_SYSRQ=y - CONFIG_DEBUG_STACK_USAGE=y -@@ -375,5 +364,4 @@ CONFIG_SOFTLOCKUP_DETECTOR=y - # CONFIG_DETECT_HUNG_TASK is not set - CONFIG_PANIC_TIMEOUT=5 - CONFIG_SCHEDSTATS=y --CONFIG_RCU_CPU_STALL_TIMEOUT=60 - # CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/patches/ANDROID-gki_defconfig-Remove-recommended-configs-not-present-on-b1c1.patch b/patches/ANDROID-gki_defconfig-Remove-recommended-configs-not-present-on-b1c1.patch deleted file mode 100644 index 26b735eedcaa3ea52a027559fe176391339b5ebf..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-Remove-recommended-configs-not-present-on-b1c1.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Sat, 4 May 2019 17:45:04 -0700 -Subject: ANDROID: gki_defconfig: Remove recommended configs not present on - b1c1 - -Enable: -CONFIG_USB because it's required. -CONFIG_OVERLAY_FS, CONFIG_ARM64_SW_TTBR0_PAN because cuttlefish doesn't -boot without these. - -CONFIG_PSI, CONFIG_DM_BOW, CONFIG_HIDRAW, CONFIG_USB_HIDDEV, -CONFIG_MSDOS_FS, CONFIG_PANIC_TIMEOUT=5 are not strictly required, but -seem appropriate for a "generic" kernel. - -Note that cuttlefish-specific modules, that are neither required nor -recommended, are still enabled. - -Test: boot cuttlefish on a arm64 machine -Signed-off-by: Tri Vo -(partially cherry picked from commit 37381a5b77c8496a5bc5827ddbaf106e51d2c0c0) ---- - arch/arm64/configs/gki_defconfig | 68 +------------------------------- - 1 file changed, 1 insertion(+), 67 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index a87cf1871f12..a747e222db8e 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -3,7 +3,6 @@ CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y - CONFIG_PREEMPT=y - CONFIG_TASKSTATS=y --CONFIG_TASK_DELAY_ACCT=y - CONFIG_TASK_XACCT=y - CONFIG_TASK_IO_ACCOUNTING=y - CONFIG_PSI=y -@@ -49,7 +48,6 @@ CONFIG_COMPAT=y - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set --CONFIG_PM_DEBUG=y - CONFIG_ENERGY_MODEL=y - CONFIG_CPU_IDLE=y - CONFIG_ARM_CPUIDLE=y -@@ -176,7 +174,6 @@ CONFIG_IP6_NF_RAW=y - CONFIG_L2TP=y - CONFIG_NET_SCHED=y - CONFIG_NET_SCH_HTB=y --CONFIG_NET_SCH_NETEM=y - CONFIG_NET_SCH_INGRESS=y - CONFIG_NET_CLS_U32=y - CONFIG_NET_CLS_BPF=y -@@ -259,15 +256,6 @@ CONFIG_INPUT_EVDEV=y - # CONFIG_INPUT_KEYBOARD is not set - # CONFIG_INPUT_MOUSE is not set - CONFIG_INPUT_JOYSTICK=y --CONFIG_JOYSTICK_XPAD=y --CONFIG_JOYSTICK_XPAD_FF=y --CONFIG_JOYSTICK_XPAD_LEDS=y --CONFIG_INPUT_TABLET=y --CONFIG_TABLET_USB_ACECAD=y --CONFIG_TABLET_USB_AIPTEK=y --CONFIG_TABLET_USB_GTCO=y --CONFIG_TABLET_USB_HANWANG=y --CONFIG_TABLET_USB_KBTAB=y - CONFIG_INPUT_MISC=y - CONFIG_INPUT_UINPUT=y - # CONFIG_VT is not set -@@ -309,65 +297,13 @@ CONFIG_SND_INTEL8X0=y - # CONFIG_SND_USB is not set - CONFIG_HIDRAW=y - CONFIG_UHID=y --CONFIG_HID_A4TECH=y --CONFIG_HID_ACRUX=y --CONFIG_HID_ACRUX_FF=y - CONFIG_HID_APPLE=y --CONFIG_HID_BELKIN=y --CONFIG_HID_CHERRY=y --CONFIG_HID_CHICONY=y --CONFIG_HID_PRODIKEYS=y --CONFIG_HID_CYPRESS=y --CONFIG_HID_DRAGONRISE=y --CONFIG_DRAGONRISE_FF=y --CONFIG_HID_EMS_FF=y - CONFIG_HID_ELECOM=y --CONFIG_HID_EZKEY=y --CONFIG_HID_HOLTEK=y --CONFIG_HID_KEYTOUCH=y --CONFIG_HID_KYE=y --CONFIG_HID_UCLOGIC=y --CONFIG_HID_WALTOP=y --CONFIG_HID_GYRATION=y --CONFIG_HID_TWINHAN=y --CONFIG_HID_KENSINGTON=y --CONFIG_HID_LCPOWER=y --CONFIG_HID_LOGITECH=y --CONFIG_HID_LOGITECH_DJ=y --CONFIG_LOGITECH_FF=y --CONFIG_LOGIRUMBLEPAD2_FF=y --CONFIG_LOGIG940_FF=y - CONFIG_HID_MAGICMOUSE=y - CONFIG_HID_MICROSOFT=y --CONFIG_HID_MONTEREY=y - CONFIG_HID_MULTITOUCH=y --CONFIG_HID_NTRIG=y --CONFIG_HID_ORTEK=y --CONFIG_HID_PANTHERLORD=y --CONFIG_PANTHERLORD_FF=y --CONFIG_HID_PETALYNX=y --CONFIG_HID_PICOLCD=y --CONFIG_HID_PRIMAX=y --CONFIG_HID_ROCCAT=y --CONFIG_HID_SAITEK=y --CONFIG_HID_SAMSUNG=y --CONFIG_HID_SONY=y --CONFIG_HID_SPEEDLINK=y --CONFIG_HID_SUNPLUS=y --CONFIG_HID_GREENASIA=y --CONFIG_GREENASIA_FF=y --CONFIG_HID_SMARTJOYPLUS=y --CONFIG_SMARTJOYPLUS_FF=y --CONFIG_HID_TIVO=y --CONFIG_HID_TOPSEED=y --CONFIG_HID_THRUSTMASTER=y --CONFIG_HID_WACOM=y --CONFIG_HID_WIIMOTE=y --CONFIG_HID_ZEROPLUS=y --CONFIG_HID_ZYDACRON=y - CONFIG_USB_HIDDEV=y --CONFIG_USB_ANNOUNCE_NEW_DEVICES=y --CONFIG_USB_EHCI_HCD=y -+CONFIG_USB=y - CONFIG_USB_GADGET=y - CONFIG_USB_CONFIGFS=y - CONFIG_USB_CONFIGFS_UEVENT=y -@@ -418,7 +354,6 @@ CONFIG_PSTORE_RAM=y - CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y - CONFIG_SECURITY=y - CONFIG_SECURITY_NETWORK=y --CONFIG_LSM_MMAP_MIN_ADDR=65536 - CONFIG_HARDENED_USERCOPY=y - CONFIG_SECURITY_SELINUX=y - CONFIG_CRYPTO_ADIANTUM=y -@@ -441,5 +376,4 @@ CONFIG_SOFTLOCKUP_DETECTOR=y - CONFIG_PANIC_TIMEOUT=5 - CONFIG_SCHEDSTATS=y - CONFIG_RCU_CPU_STALL_TIMEOUT=60 --CONFIG_ENABLE_DEFAULT_TRACERS=y - # CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/patches/ANDROID-gki_defconfig-common-configs-for-device-DLKMs.patch b/patches/ANDROID-gki_defconfig-common-configs-for-device-DLKMs.patch deleted file mode 100644 index 4453ed6a43cd3d91958ecc02746d15e975e27126..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-common-configs-for-device-DLKMs.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Sat, 11 May 2019 16:48:08 -0700 -Subject: ANDROID: gki_defconfig: common configs for device DLKMs - -Test: boot arm64 cuttlefish -Signed-off-by: Tri Vo -(partially cherry picked from commit 6742f3f75046867373ac782e709681c98f72a744) ---- - arch/arm64/configs/gki_defconfig | 18 ++++++++++++++++-- - 1 file changed, 16 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 41a892ca324d..cc9ecd83a69c 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -269,22 +269,30 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_DEVPORT is not set - # CONFIG_I2C_COMPAT is not set - # CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_SPMI=y -+CONFIG_GPIOLIB=y - # CONFIG_HWMON is not set - CONFIG_THERMAL=y -+CONFIG_THERMAL_GOV_USER_SPACE=y - CONFIG_CPU_THERMAL=y -+CONFIG_DEVFREQ_THERMAL=y -+CONFIG_REGULATOR=y - CONFIG_MEDIA_SUPPORT=y -+CONFIG_MEDIA_CAMERA_SUPPORT=y - # CONFIG_VGA_ARB is not set - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set - CONFIG_DRM_VIRTIO_GPU=y -+CONFIG_BACKLIGHT_LCD_SUPPORT=y -+CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_SOUND=y - CONFIG_SND=y - CONFIG_SND_HRTIMER=y -+CONFIG_SND_DYNAMIC_MINORS=y - # CONFIG_SND_SUPPORT_OLD_API is not set - # CONFIG_SND_VERBOSE_PROCFS is not set - # CONFIG_SND_DRIVERS is not set - CONFIG_SND_INTEL8X0=y --# CONFIG_SND_USB is not set - CONFIG_HIDRAW=y - CONFIG_UHID=y - CONFIG_HID_APPLE=y -@@ -305,6 +313,9 @@ CONFIG_MMC=y - # CONFIG_PWRSEQ_EMMC is not set - # CONFIG_PWRSEQ_SIMPLE is not set - # CONFIG_MMC_BLOCK is not set -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_TRIGGERS=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_SYSTOHC is not set - CONFIG_RTC_DRV_PL030=y -@@ -321,7 +332,9 @@ CONFIG_ANDROID_VSOC=y - CONFIG_ION=y - CONFIG_COMMON_CLK_SCPI=y - CONFIG_MAILBOX=y --# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_PM_DEVFREQ=y -+CONFIG_PWM=y -+CONFIG_GENERIC_PHY=y - CONFIG_ANDROID=y - CONFIG_ANDROID_BINDER_IPC=y - CONFIG_EXT4_FS=y -@@ -352,6 +365,7 @@ CONFIG_CRYPTO_LZ4=y - CONFIG_CRYPTO_ZSTD=y - CONFIG_CRYPTO_ANSI_CPRNG=y - CONFIG_CRYPTO_DEV_VIRTIO=y -+CONFIG_CRC8=y - CONFIG_XZ_DEC=y - CONFIG_PRINTK_TIME=y - CONFIG_DEBUG_INFO=y diff --git a/patches/ANDROID-gki_defconfig-disable-BRIDGE_NETFILTER.patch b/patches/ANDROID-gki_defconfig-disable-BRIDGE_NETFILTER.patch deleted file mode 100644 index 9c8776f20068de127b0af52ef273a56e3617629e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-disable-BRIDGE_NETFILTER.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Wed, 17 Jul 2019 15:25:54 -0700 -Subject: ANDROID: gki_defconfig: disable BRIDGE_NETFILTER - -This config is explicitly disabled on Pixel 3. - -Change-Id: I126e5222180e3880a71c0f78b99276b0157ef4c8 -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 45644397a2d7..140804afdd32 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -101,6 +101,7 @@ CONFIG_IPV6_MIP6=y - CONFIG_IPV6_VTI=y - CONFIG_IPV6_MULTIPLE_TABLES=y - CONFIG_NETFILTER=y -+# CONFIG_BRIDGE_NETFILTER is not set - CONFIG_NF_CONNTRACK=y - CONFIG_NF_CONNTRACK_SECMARK=y - CONFIG_NF_CONNTRACK_EVENTS=y diff --git a/patches/ANDROID-gki_defconfig-disable-CONFIG_LCD_CLASS_DEVICE-module.patch b/patches/ANDROID-gki_defconfig-disable-CONFIG_LCD_CLASS_DEVICE-module.patch deleted file mode 100644 index 029c7e8a77f7ecea3d1241e53668fee088bd2176..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-disable-CONFIG_LCD_CLASS_DEVICE-module.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Tue, 14 May 2019 17:32:43 -0700 -Subject: ANDROID: gki_defconfig: disable CONFIG_LCD_CLASS_DEVICE module - -CONFIG_LCD_CLASS_DEVICE is set to "m" by default when -CONFIG_BACKLIGHT_LCD_SUPPORT is set. We don't need lcd.ko though. ---- - arch/arm64/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index cc9ecd83a69c..4b17f0f9d0ae 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -284,6 +284,7 @@ CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set - CONFIG_DRM_VIRTIO_GPU=y - CONFIG_BACKLIGHT_LCD_SUPPORT=y -+# CONFIG_LCD_CLASS_DEVICE is not set - CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_SOUND=y - CONFIG_SND=y diff --git a/patches/ANDROID-gki_defconfig-disable-IP_PNP-ECRYPT_FS.patch b/patches/ANDROID-gki_defconfig-disable-IP_PNP-ECRYPT_FS.patch deleted file mode 100644 index ba50ac2937b677196106e57f71b9e51acdfcd9fc..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-disable-IP_PNP-ECRYPT_FS.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Thu, 8 Aug 2019 17:06:26 -0700 -Subject: ANDROID: gki_defconfig: disable IP_PNP, ECRYPT_FS - -Neither are necessary on android devices. - -Change-Id: I61008f47c53fb88fcdbdcd889346a214b23246ad -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 43a1fea94c6a..539f42574383 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -87,7 +87,6 @@ CONFIG_INET=y - CONFIG_IP_MULTICAST=y - CONFIG_IP_ADVANCED_ROUTER=y - CONFIG_IP_MULTIPLE_TABLES=y --CONFIG_IP_PNP=y - CONFIG_NET_IPGRE_DEMUX=y - CONFIG_NET_IPVTI=y - CONFIG_INET_ESP=y -@@ -379,7 +378,6 @@ CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y --CONFIG_ECRYPT_FS=y - CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y diff --git a/patches/ANDROID-gki_defconfig-enable-CMA-and-increase-CMA_AREAS.patch b/patches/ANDROID-gki_defconfig-enable-CMA-and-increase-CMA_AREAS.patch deleted file mode 100644 index 1132f5b9cece36407a785ded171c17e4471fd762..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-CMA-and-increase-CMA_AREAS.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Mon, 3 Jun 2019 11:50:28 -0700 -Subject: ANDROID: gki_defconfig: enable CMA and increase CMA_AREAS - -Fixes: 134378085 -Test: boot arm64 cuttlefish -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index c9720858fd9a..bf15919ba7e7 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -66,6 +66,8 @@ CONFIG_MODVERSIONS=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set - # CONFIG_SPARSEMEM_VMEMMAP is not set - CONFIG_TRANSPARENT_HUGEPAGE=y -+CONFIG_CMA=y -+CONFIG_CMA_AREAS=16 - CONFIG_ZSMALLOC=y - CONFIG_NET=y - CONFIG_PACKET=y diff --git a/patches/ANDROID-gki_defconfig-enable-CONFIG_NLS_.patch b/patches/ANDROID-gki_defconfig-enable-CONFIG_NLS_.patch deleted file mode 100644 index 9f5b623ef1bdb78b88d015934a5db588937d83ac..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-CONFIG_NLS_.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Tue, 8 Oct 2019 15:12:37 -0700 -Subject: ANDROID: gki_defconfig: enable CONFIG_NLS_* - -CONFIG_NLS_CODEPAGE_437 and CONFIG_NLS_ISO8859_1 are needed by cuttlefish -to pass the CTS test - StorageManagerTest#testMountAndUnmountObbNormal - -Adding the remaining 47 NLS Configs to account for possible i18n -requirements not caught by CTS/VTS - -Bug: 138199351 -Change-Id: I897873c8454f8329f4dc53d9af71907ba71790b7 -Signed-off-by: Ram Muthiah ---- - arch/arm64/configs/gki_defconfig | 49 ++++++++++++++++++++++++++++++++ - arch/x86/configs/gki_defconfig | 49 ++++++++++++++++++++++++++++++++ - 2 files changed, 98 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 0b7669f8fedd..29cc5898a871 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -391,6 +391,55 @@ CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y - CONFIG_PSTORE_RAM=y -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=y -+CONFIG_NLS_CODEPAGE_775=y -+CONFIG_NLS_CODEPAGE_850=y -+CONFIG_NLS_CODEPAGE_852=y -+CONFIG_NLS_CODEPAGE_855=y -+CONFIG_NLS_CODEPAGE_857=y -+CONFIG_NLS_CODEPAGE_860=y -+CONFIG_NLS_CODEPAGE_861=y -+CONFIG_NLS_CODEPAGE_862=y -+CONFIG_NLS_CODEPAGE_863=y -+CONFIG_NLS_CODEPAGE_864=y -+CONFIG_NLS_CODEPAGE_865=y -+CONFIG_NLS_CODEPAGE_866=y -+CONFIG_NLS_CODEPAGE_869=y -+CONFIG_NLS_CODEPAGE_936=y -+CONFIG_NLS_CODEPAGE_950=y -+CONFIG_NLS_CODEPAGE_932=y -+CONFIG_NLS_CODEPAGE_949=y -+CONFIG_NLS_CODEPAGE_874=y -+CONFIG_NLS_ISO8859_8=y -+CONFIG_NLS_CODEPAGE_1250=y -+CONFIG_NLS_CODEPAGE_1251=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_2=y -+CONFIG_NLS_ISO8859_3=y -+CONFIG_NLS_ISO8859_4=y -+CONFIG_NLS_ISO8859_5=y -+CONFIG_NLS_ISO8859_6=y -+CONFIG_NLS_ISO8859_7=y -+CONFIG_NLS_ISO8859_9=y -+CONFIG_NLS_ISO8859_13=y -+CONFIG_NLS_ISO8859_14=y -+CONFIG_NLS_ISO8859_15=y -+CONFIG_NLS_KOI8_R=y -+CONFIG_NLS_KOI8_U=y -+CONFIG_NLS_MAC_ROMAN=y -+CONFIG_NLS_MAC_CELTIC=y -+CONFIG_NLS_MAC_CENTEURO=y -+CONFIG_NLS_MAC_CROATIAN=y -+CONFIG_NLS_MAC_CYRILLIC=y -+CONFIG_NLS_MAC_GAELIC=y -+CONFIG_NLS_MAC_GREEK=y -+CONFIG_NLS_MAC_ICELAND=y -+CONFIG_NLS_MAC_INUIT=y -+CONFIG_NLS_MAC_ROMANIAN=y -+CONFIG_NLS_MAC_TURKISH=y -+CONFIG_NLS_UTF8=y - CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y - CONFIG_SECURITY=y - CONFIG_SECURITY_NETWORK=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 78283ea8c1c8..5059dcaf01bb 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -324,6 +324,55 @@ CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y - CONFIG_PSTORE_RAM=y -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=y -+CONFIG_NLS_CODEPAGE_775=y -+CONFIG_NLS_CODEPAGE_850=y -+CONFIG_NLS_CODEPAGE_852=y -+CONFIG_NLS_CODEPAGE_855=y -+CONFIG_NLS_CODEPAGE_857=y -+CONFIG_NLS_CODEPAGE_860=y -+CONFIG_NLS_CODEPAGE_861=y -+CONFIG_NLS_CODEPAGE_862=y -+CONFIG_NLS_CODEPAGE_863=y -+CONFIG_NLS_CODEPAGE_864=y -+CONFIG_NLS_CODEPAGE_865=y -+CONFIG_NLS_CODEPAGE_866=y -+CONFIG_NLS_CODEPAGE_869=y -+CONFIG_NLS_CODEPAGE_936=y -+CONFIG_NLS_CODEPAGE_950=y -+CONFIG_NLS_CODEPAGE_932=y -+CONFIG_NLS_CODEPAGE_949=y -+CONFIG_NLS_CODEPAGE_874=y -+CONFIG_NLS_ISO8859_8=y -+CONFIG_NLS_CODEPAGE_1250=y -+CONFIG_NLS_CODEPAGE_1251=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_2=y -+CONFIG_NLS_ISO8859_3=y -+CONFIG_NLS_ISO8859_4=y -+CONFIG_NLS_ISO8859_5=y -+CONFIG_NLS_ISO8859_6=y -+CONFIG_NLS_ISO8859_7=y -+CONFIG_NLS_ISO8859_9=y -+CONFIG_NLS_ISO8859_13=y -+CONFIG_NLS_ISO8859_14=y -+CONFIG_NLS_ISO8859_15=y -+CONFIG_NLS_KOI8_R=y -+CONFIG_NLS_KOI8_U=y -+CONFIG_NLS_MAC_ROMAN=y -+CONFIG_NLS_MAC_CELTIC=y -+CONFIG_NLS_MAC_CENTEURO=y -+CONFIG_NLS_MAC_CROATIAN=y -+CONFIG_NLS_MAC_CYRILLIC=y -+CONFIG_NLS_MAC_GAELIC=y -+CONFIG_NLS_MAC_GREEK=y -+CONFIG_NLS_MAC_ICELAND=y -+CONFIG_NLS_MAC_INUIT=y -+CONFIG_NLS_MAC_ROMANIAN=y -+CONFIG_NLS_MAC_TURKISH=y -+CONFIG_NLS_UTF8=y - CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y - CONFIG_SECURITY=y - CONFIG_SECURITY_NETWORK=y diff --git a/patches/ANDROID-gki_defconfig-enable-CONFIG_PARAVIRT-and-CONFIG_HYPERVISOR_GUEST.patch b/patches/ANDROID-gki_defconfig-enable-CONFIG_PARAVIRT-and-CONFIG_HYPERVISOR_GUEST.patch deleted file mode 100644 index 7c8f54ea5c5caac51d9698eeade2af4f8d9919e1..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-CONFIG_PARAVIRT-and-CONFIG_HYPERVISOR_GUEST.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Thu, 10 Oct 2019 08:45:15 -0700 -Subject: ANDROID: gki_defconfig: enable CONFIG_PARAVIRT and - CONFIG_HYPERVISOR_GUEST - -CONFIG_HYPERVISOR_GUEST is needed by cuttlefish to pass the CTS Bionic tests: -clock_getres_CLOCK_MONOTONIC, clock_getres_CLOCK_REALTIME, and -clock_getres_CLOCK_BOOTTIME - -Bug: 138199351 -Change-Id: I3e209035cdd7a29e020078f8aba567d9c8446347 -Signed-off-by: Ram Muthiah ---- - arch/x86/configs/gki_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 5059dcaf01bb..0e23b0cc3a8c 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -37,6 +37,8 @@ CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y - CONFIG_SMP=y -+CONFIG_HYPERVISOR_GUEST=y -+CONFIG_PARAVIRT=y - CONFIG_NR_CPUS=32 - CONFIG_EFI=y - CONFIG_PM_WAKELOCKS=y diff --git a/patches/ANDROID-gki_defconfig-enable-CONFIG_QCOM_-COMMAND_DB-RPMH-PDC.patch b/patches/ANDROID-gki_defconfig-enable-CONFIG_QCOM_-COMMAND_DB-RPMH-PDC.patch deleted file mode 100644 index 0f91c2fb992b618658efe34e79ef5bb6b7459c04..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-CONFIG_QCOM_-COMMAND_DB-RPMH-PDC.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Thu, 29 Aug 2019 14:04:15 -0700 -Subject: ANDROID: gki_defconfig: enable CONFIG_QCOM_{COMMAND_DB,RPMH,PDC} - -CONFIG_ARCH_QCOM is a dependency of the above and selects -CONFIG_{PINCTRL, REGULATOR, TMPFS}. - -Bug: 133441279 -Bug: 133441092 -Bug: 133440650 -Change-Id: I22c37946ec3a62ccbd3fa65bbc09076964d86475 -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 604b97841737..6aae6d55e96c 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -36,6 +36,7 @@ CONFIG_EMBEDDED=y - CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y -+CONFIG_ARCH_QCOM=y - CONFIG_SCHED_MC=y - CONFIG_NR_CPUS=32 - CONFIG_SECCOMP=y -@@ -279,7 +280,6 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_I2C_HELPER_AUTO is not set - CONFIG_SPI=y - CONFIG_SPMI=y --CONFIG_PINCTRL=y - CONFIG_PINCTRL_AMD=y - CONFIG_POWER_AVS=y - # CONFIG_HWMON is not set -@@ -290,7 +290,6 @@ CONFIG_DEVFREQ_THERMAL=y - CONFIG_WATCHDOG=y - CONFIG_MFD_ACT8945A=y - CONFIG_MFD_SYSCON=y --CONFIG_REGULATOR=y - CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_CONTROLLER=y -@@ -357,12 +356,15 @@ CONFIG_COMMON_CLK_SCPI=y - CONFIG_HWSPINLOCK=y - CONFIG_MAILBOX=y - CONFIG_ARM_SMMU=y -+CONFIG_QCOM_COMMAND_DB=y -+CONFIG_QCOM_RPMH=y - CONFIG_DEVFREQ_GOV_PERFORMANCE=y - CONFIG_DEVFREQ_GOV_POWERSAVE=y - CONFIG_DEVFREQ_GOV_USERSPACE=y - CONFIG_DEVFREQ_GOV_PASSIVE=y - CONFIG_EXTCON=y - CONFIG_PWM=y -+CONFIG_QCOM_PDC=y - CONFIG_GENERIC_PHY=y - CONFIG_RAS=y - CONFIG_ANDROID=y -@@ -380,7 +382,6 @@ CONFIG_FUSE_FS=y - CONFIG_OVERLAY_FS=y - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y --CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y - # CONFIG_EFIVAR_FS is not set - CONFIG_SDCARD_FS=y diff --git a/patches/ANDROID-gki_defconfig-enable-CONFIG_SPARSEMEM_VMEMMAP.patch b/patches/ANDROID-gki_defconfig-enable-CONFIG_SPARSEMEM_VMEMMAP.patch deleted file mode 100644 index 899cf541655850a9ae8cd80518977a3a1e2e0e8c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-CONFIG_SPARSEMEM_VMEMMAP.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Salyzyn -Date: Thu, 29 Aug 2019 08:00:26 -0700 -Subject: ANDROID: gki_defconfig enable CONFIG_SPARSEMEM_VMEMMAP - -Legacy Ion driver and SPARSEMEM for carveout regions results -in invalid page structures breaking page_to_pfn(). This can -be temporarily resolved with SPARSEMEM_VMEMMAP until the Ion -driver is refactored and can be reinvestigated. - -At that time if it can be solved, or maybe correct this issue -utilizing less resources than SPARSEMEM_VMEMMAP requires. The -ABI does not change so we have the flexibility to adjust this -configuration. - -Signed-off-by: Mark Salyzyn -Bug: 138851285 -Bug: 138149732 -Test: ABI_DEFINITION=common/abi_gki_aarch64.xml \ - BUILD_CONFIG=common/build.config.gki.aarch64 ./build/build_abi.sh -Change-Id: I25cc8ebe9e25260b9869c5e8d8667b280f83ca51 ---- - arch/arm64/configs/gki_defconfig | 1 - - arch/x86/configs/gki_defconfig | 1 - - 2 files changed, 2 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 006692f065d4..604b97841737 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -72,7 +72,6 @@ CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set --# CONFIG_SPARSEMEM_VMEMMAP is not set - CONFIG_MEMORY_HOTPLUG=y - CONFIG_TRANSPARENT_HUGEPAGE=y - CONFIG_CMA=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index ed8296e953ed..e86cd1009a67 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -48,7 +48,6 @@ CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set --# CONFIG_SPARSEMEM_VMEMMAP is not set - CONFIG_TRANSPARENT_HUGEPAGE=y - CONFIG_CMA=y - CONFIG_CMA_AREAS=16 diff --git a/patches/ANDROID-gki_defconfig-enable-CONFIG_TIPC.patch b/patches/ANDROID-gki_defconfig-enable-CONFIG_TIPC.patch deleted file mode 100644 index 82ab1f640a761377873522770e3cd54fedc1e28c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-CONFIG_TIPC.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Fri, 23 Aug 2019 10:57:25 -0700 -Subject: ANDROID: gki_defconfig: enable CONFIG_TIPC - -Test: n/a -Change-Id: If068edf432bd2574a9ca8257e5a4f43731328317 -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 73acbe383203..b70d608b1ee6 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -170,6 +170,7 @@ CONFIG_IP6_NF_FILTER=y - 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_NET_SCHED=y diff --git a/patches/ANDROID-gki_defconfig-enable-CONFIG_UIO.patch b/patches/ANDROID-gki_defconfig-enable-CONFIG_UIO.patch deleted file mode 100644 index 27f513271d2cf3539fa649e828e4c207ea4a75d5..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-CONFIG_UIO.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Wed, 18 Sep 2019 14:07:28 -0700 -Subject: ANDROID: gki_defconfig: enable CONFIG_UIO - -Bug: 135666008 -Change-Id: I1fac71548c2f442d3622ff068928662d1ba6e3dd -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 440173b3c301..f65b544d17a4 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -337,6 +337,7 @@ CONFIG_RTC_CLASS=y - CONFIG_RTC_DRV_PL030=y - CONFIG_RTC_DRV_PL031=y - CONFIG_DMADEVICES=y -+CONFIG_UIO=y - CONFIG_VIRTIO_PCI=y - # CONFIG_VIRTIO_PCI_LEGACY is not set - CONFIG_VIRTIO_INPUT=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index c206a2d0f9cf..3e8f580e0bde 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -287,6 +287,7 @@ CONFIG_LEDS_TRIGGERS=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_SYSTOHC is not set - CONFIG_RTC_DRV_TEST=m -+CONFIG_UIO=y - CONFIG_VIRTIO_PCI=m - CONFIG_VIRTIO_INPUT=m - CONFIG_VIRTIO_MMIO=m diff --git a/patches/ANDROID-gki_defconfig-enable-DMA_CMA.patch b/patches/ANDROID-gki_defconfig-enable-DMA_CMA.patch deleted file mode 100644 index 0fae24345dfdf05deec629c731484629eb3c82a7..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-DMA_CMA.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Wed, 12 Jun 2019 15:26:49 -0700 -Subject: ANDROID: gki_defconfig: enable DMA_CMA - -And update ABI representation. - -Fixes: 134916881 -Test: boot arm64 cuttlefish -Signed-off-by: Tri Vo -Change-Id: Id0d270f510aa0a06dc5a082ef35c3d969b72cc35 ---- - arch/arm64/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index ef79e45cae16..9bc2782661dc 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -373,6 +373,7 @@ CONFIG_CRYPTO_ANSI_CPRNG=y - CONFIG_CRYPTO_DEV_VIRTIO=y - CONFIG_CRC8=y - CONFIG_XZ_DEC=y -+CONFIG_DMA_CMA=y - CONFIG_PRINTK_TIME=y - CONFIG_DEBUG_INFO=y - # CONFIG_ENABLE_MUST_CHECK is not set diff --git a/patches/ANDROID-gki_defconfig-enable-REGULATOR.patch b/patches/ANDROID-gki_defconfig-enable-REGULATOR.patch deleted file mode 100644 index 6d9f0f2670a925acf238a651f7ee7529cae7e0db..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-REGULATOR.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Tue, 8 Oct 2019 12:38:34 -0700 -Subject: ANDROID: gki_defconfig: enable REGULATOR - -Fixes: 142334529 -Change-Id: If2e17aec00c2f2202f6f9203192afcd8e12228a6 -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 9e3b34fa8b64..0b7669f8fedd 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -293,6 +293,7 @@ CONFIG_DEVFREQ_THERMAL=y - CONFIG_WATCHDOG=y - CONFIG_MFD_ACT8945A=y - CONFIG_MFD_SYSCON=y -+CONFIG_REGULATOR=y - CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_CONTROLLER=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index f539970bf631..78283ea8c1c8 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -252,6 +252,7 @@ CONFIG_GPIOLIB=y - # CONFIG_HWMON is not set - CONFIG_DEVFREQ_THERMAL=y - # CONFIG_X86_PKG_TEMP_THERMAL is not set -+CONFIG_REGULATOR=y - CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_DRM=y diff --git a/patches/ANDROID-gki_defconfig-enable-SLAB_FREELIST_RANDOM-SLAB_FREELIST_HARDENED.patch b/patches/ANDROID-gki_defconfig-enable-SLAB_FREELIST_RANDOM-SLAB_FREELIST_HARDENED.patch deleted file mode 100644 index 925a152e28d1832bfb2a9639c3c5d004e8a425bb..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-SLAB_FREELIST_RANDOM-SLAB_FREELIST_HARDENED.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Mon, 3 Jun 2019 12:54:46 -0700 -Subject: ANDROID: gki_defconfig: enable SLAB_FREELIST_RANDOM, - SLAB_FREELIST_HARDENED - -Security hardening - -Fixes: 134087016 -Test: boot arm64 cuttlefish -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index bf15919ba7e7..ef79e45cae16 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -31,6 +31,8 @@ CONFIG_EMBEDDED=y - # CONFIG_VM_EVENT_COUNTERS is not set - # CONFIG_COMPAT_BRK is not set - # CONFIG_SLAB_MERGE_DEFAULT is not set -+CONFIG_SLAB_FREELIST_RANDOM=y -+CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y - CONFIG_SCHED_MC=y - CONFIG_SECCOMP=y diff --git a/patches/ANDROID-gki_defconfig-enable-accelerated-AES-and-SHA-256.patch b/patches/ANDROID-gki_defconfig-enable-accelerated-AES-and-SHA-256.patch deleted file mode 100644 index b628bb68957f7e425cbc85be672c1d2f10f2d2e7..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-accelerated-AES-and-SHA-256.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eric Biggers -Date: Wed, 9 Oct 2019 13:00:58 -0700 -Subject: ANDROID: gki_defconfig: enable accelerated AES and SHA-256 - -Enable AES and SHA-256 accelerated with the ARM Cryptography Extensions -or with AES-NI, as recommended by -kernel-configs/android-4.19/android-recommended-{arm64,x86}.config. -These are ~10x faster than the other software implementations of AES and -SHA-256 on most devices, and often are required to get acceptable -fscrypt and dm-verity performance. - -Bug: 142410832 -Change-Id: Ia2794f47711132d5caa9021e6e81fb625e02be8d -Signed-off-by: Eric Biggers ---- - arch/arm64/configs/gki_defconfig | 3 ++- - arch/x86/configs/gki_defconfig | 2 ++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 29cc5898a871..98520ebdd4d6 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -69,7 +69,8 @@ CONFIG_ARM_SCPI_PROTOCOL=y - # CONFIG_ARM_SCPI_POWER_DOMAIN is not set - # CONFIG_EFI_ARMSTUB_DTB_LOADER is not set - CONFIG_ARM64_CRYPTO=y --CONFIG_CRYPTO_AES_ARM64=y -+CONFIG_CRYPTO_SHA2_ARM64_CE=y -+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y - CONFIG_KPROBES=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 0e23b0cc3a8c..931fcbdced69 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -381,6 +381,8 @@ CONFIG_SECURITY_NETWORK=y - CONFIG_HARDENED_USERCOPY=y - CONFIG_SECURITY_SELINUX=y - CONFIG_CRYPTO_ADIANTUM=y -+CONFIG_CRYPTO_SHA256_SSSE3=y -+CONFIG_CRYPTO_AES_NI_INTEL=y - CONFIG_CRYPTO_LZ4=y - CONFIG_CRYPTO_ZSTD=y - CONFIG_CRYPTO_ANSI_CPRNG=y diff --git a/patches/ANDROID-gki_defconfig-enable-fs-verity.patch b/patches/ANDROID-gki_defconfig-enable-fs-verity.patch deleted file mode 100644 index d0eba23c8a7961bfa91285961079409b802b7295..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-fs-verity.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eric Biggers -Date: Thu, 10 Oct 2019 15:45:41 -0700 -Subject: ANDROID: gki_defconfig: enable fs-verity - -fs-verity will be used for APK verification in R. - -Bug: 142494008 -Change-Id: Ia18eb35fcdbccabab47de5fb26daba455fc1eb77 -Signed-off-by: Eric Biggers ---- - arch/arm64/configs/gki_defconfig | 2 ++ - arch/x86/configs/gki_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index ed21a0d79f4c..80ebf75319a1 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -381,6 +381,8 @@ CONFIG_EXT4_FS_SECURITY=y - CONFIG_F2FS_FS=y - CONFIG_F2FS_FS_SECURITY=y - CONFIG_FS_ENCRYPTION=y -+CONFIG_FS_VERITY=y -+CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y - # CONFIG_DNOTIFY is not set - CONFIG_QUOTA=y - CONFIG_QFMT_V2=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index fbcf73e4f66f..18c3429c7ede 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -313,6 +313,8 @@ CONFIG_EXT4_FS_SECURITY=y - CONFIG_F2FS_FS=y - CONFIG_F2FS_FS_SECURITY=y - CONFIG_FS_ENCRYPTION=y -+CONFIG_FS_VERITY=y -+CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y - # CONFIG_DNOTIFY is not set - CONFIG_QUOTA=y - CONFIG_QFMT_V2=y diff --git a/patches/ANDROID-gki_defconfig-enable-more-configs.patch b/patches/ANDROID-gki_defconfig-enable-more-configs.patch deleted file mode 100644 index 5a144c2468b76d4ee8c6e43c7565d39d9d74343d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enable-more-configs.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Tue, 16 Jul 2019 16:27:17 -0700 -Subject: ANDROID: gki_defconfig: enable more configs - -Enable following configs: -CONFIG_RAS -CONFIG_EDAC -CONFIG_SPI -CONFIG_DMADEVICES -CONFIG_POWER_AVS -CONFIG_WATCHDOG -CONFIG_USB_OTG -CONFIG_MMC_BLOCK - -Fixes: 137124260 -Fixes: 136278478 -Fixes: 136279343 -Fixes: 136279418 -Fixes: 136279652 -Fixes: 136279658 -Fixes: 136281307 -Change-Id: I630dd2ffd4f6694b497cbb273830d643878694f6 -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 7c66f40c9739..45644397a2d7 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -274,14 +274,17 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_DEVPORT is not set - # CONFIG_I2C_COMPAT is not set - # CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_SPI=y - CONFIG_SPMI=y - CONFIG_PINCTRL=y - CONFIG_PINCTRL_AMD=y -+CONFIG_POWER_AVS=y - # CONFIG_HWMON is not set - CONFIG_THERMAL=y - CONFIG_THERMAL_GOV_USER_SPACE=y - CONFIG_CPU_THERMAL=y - CONFIG_DEVFREQ_THERMAL=y -+CONFIG_WATCHDOG=y - CONFIG_MFD_ACT8945A=y - CONFIG_MFD_SYSCON=y - CONFIG_REGULATOR=y -@@ -313,6 +316,7 @@ CONFIG_HID_MICROSOFT=y - CONFIG_HID_MULTITOUCH=y - CONFIG_USB_HIDDEV=y - CONFIG_USB=y -+CONFIG_USB_OTG=y - CONFIG_USB_GADGET=y - CONFIG_USB_DUMMY_HCD=y - CONFIG_USB_CONFIGFS=y -@@ -324,16 +328,17 @@ CONFIG_USB_CONFIGFS_F_MIDI=y - CONFIG_MMC=y - # CONFIG_PWRSEQ_EMMC is not set - # CONFIG_PWRSEQ_SIMPLE is not set --# CONFIG_MMC_BLOCK is not set - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_NEW_LEDS=y - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y -+CONFIG_EDAC=y - CONFIG_RTC_CLASS=y - # CONFIG_RTC_SYSTOHC is not set - CONFIG_RTC_DRV_PL030=y - CONFIG_RTC_DRV_PL031=y -+CONFIG_DMADEVICES=y - CONFIG_VIRTIO_PCI=y - # CONFIG_VIRTIO_PCI_LEGACY is not set - CONFIG_VIRTIO_INPUT=y -@@ -354,6 +359,7 @@ CONFIG_DEVFREQ_GOV_PASSIVE=y - CONFIG_EXTCON=y - CONFIG_PWM=y - CONFIG_GENERIC_PHY=y -+CONFIG_RAS=y - CONFIG_ANDROID=y - CONFIG_ANDROID_BINDER_IPC=y - CONFIG_INTERCONNECT=y diff --git a/patches/ANDROID-gki_defconfig-enabled-CONFIG_TMPFS-explicitly.patch b/patches/ANDROID-gki_defconfig-enabled-CONFIG_TMPFS-explicitly.patch deleted file mode 100644 index 950b0bb248b69a0fa60fef03d6a97ddad43ffaf1..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-enabled-CONFIG_TMPFS-explicitly.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yongqin Liu -Date: Thu, 10 Oct 2019 11:35:16 +0800 -Subject: ANDROID: gki_defconfig: enabled CONFIG_TMPFS explicitly - -otherwise will cause init boot failure reported like this: - -[ 1.959344] Run /init as init process -[ 1.966119] tmpfs: Unknown parameter 'mode' -[ 1.971092] tmpfs: Unknown parameter 'mode' -[ 1.975426] tmpfs: Unknown parameter 'mode' -[ 1.979709] tmpfs: Unknown parameter 'mode' -[ 1.984298] init: mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755") failed Invalid argument -[ 1.993214] init: mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=1000") failed Invalid argument -[ 2.005417] init: mount("tmpfs", "/apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0") failed Invalid argument -[ 2.017435] init: mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0") failed Invalid argument -[ 2.030276] init: Init encountered errors starting first stage, aborting -[ 2.057074] init: #00 pc 00000000002eeac8 /init (UnwindStackCurrent::UnwindFromContext(unsigned long, void*)+96) -[ 2.067403] init: #01 pc 00000000002730c4 /init (android::init::InitFatalReboot()+92) -[ 2.075341] init: #02 pc 00000000002754f4 /init (android::init::InitAborter(char const*)+44) -[ 2.083887] init: #03 pc 00000000002ae4f8 /init (android::base::LogMessage::~LogMessage()+608) -[ 2.092605] init: #04 pc 000000000026aba8 /init (android::init::FirstStageMain(int, char**)+4400) -[ 2.101588] init: #05 pc 00000000003599e4 /init (__real_libc_init(void*, void (*)(), int (*)(int, char**, char**), structors_array_t const*, bionic_tcb*)+572) -[ 2.115863] init: Reboot ending, jumping to kernel -[ 2.121709] reboot: Restarting system with command 'bootloader' - -Tested: with hikey - -Change-Id: I607856cbcc5bfdaf304b13089c07ca0cf10c2f76 -Signed-off-by: Yongqin Liu ---- - arch/arm64/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 98520ebdd4d6..6ccf6c7ef9ec 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -387,6 +387,7 @@ CONFIG_FUSE_FS=y - CONFIG_OVERLAY_FS=y - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y - # CONFIG_EFIVAR_FS is not set - CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y diff --git a/patches/ANDROID-gki_defconfig-initial-config-based-on-cuttlefish_defconfig.patch b/patches/ANDROID-gki_defconfig-initial-config-based-on-cuttlefish_defconfig.patch deleted file mode 100644 index 3ad69bcba47dac36663b8bdb64133a883723e9ee..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-initial-config-based-on-cuttlefish_defconfig.patch +++ /dev/null @@ -1,463 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Mon, 13 May 2019 16:00:04 -0700 -Subject: ANDROID: gki_defconfig: initial config based on cuttlefish_defconfig - -Test: boot arm64 cuttlefish -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 445 +++++++++++++++++++++++++++++++ - 1 file changed, 445 insertions(+) - create mode 100644 arch/arm64/configs/gki_defconfig - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -new file mode 100644 -index 000000000000..a87cf1871f12 ---- /dev/null -+++ b/arch/arm64/configs/gki_defconfig -@@ -0,0 +1,445 @@ -+CONFIG_AUDIT=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_PREEMPT=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_PSI=y -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_MEMCG=y -+CONFIG_MEMCG_SWAP=y -+CONFIG_RT_GROUP_SCHED=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CPUSETS=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_CGROUP_BPF=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_RD_BZIP2 is not set -+# CONFIG_RD_LZMA is not set -+# CONFIG_RD_XZ is not set -+# CONFIG_RD_LZO is not set -+# CONFIG_RD_LZ4 is not set -+CONFIG_SGETMASK_SYSCALL=y -+# CONFIG_SYSFS_SYSCALL is not set -+# CONFIG_FHANDLE is not set -+CONFIG_KALLSYMS_ALL=y -+CONFIG_BPF_SYSCALL=y -+# CONFIG_RSEQ is not set -+CONFIG_EMBEDDED=y -+# CONFIG_VM_EVENT_COUNTERS is not set -+# CONFIG_COMPAT_BRK is not set -+# CONFIG_SLAB_MERGE_DEFAULT is not set -+CONFIG_PROFILING=y -+CONFIG_SCHED_MC=y -+CONFIG_HZ_100=y -+CONFIG_SECCOMP=y -+CONFIG_PARAVIRT=y -+CONFIG_ARMV8_DEPRECATED=y -+CONFIG_SWP_EMULATION=y -+CONFIG_CP15_BARRIER_EMULATION=y -+CONFIG_SETEND_EMULATION=y -+CONFIG_ARM64_SW_TTBR0_PAN=y -+CONFIG_RANDOMIZE_BASE=y -+# CONFIG_EFI is not set -+CONFIG_COMPAT=y -+CONFIG_PM_WAKELOCKS=y -+CONFIG_PM_WAKELOCKS_LIMIT=0 -+# CONFIG_PM_WAKELOCKS_GC is not set -+CONFIG_PM_DEBUG=y -+CONFIG_ENERGY_MODEL=y -+CONFIG_CPU_IDLE=y -+CONFIG_ARM_CPUIDLE=y -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_TIMES=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_CPUFREQ_DT=y -+CONFIG_ARM_SCPI_CPUFREQ=y -+CONFIG_ARM_SCMI_CPUFREQ=y -+CONFIG_ARM_SCMI_PROTOCOL=y -+# CONFIG_ARM_SCMI_POWER_DOMAIN is not set -+CONFIG_ARM_SCPI_PROTOCOL=y -+# CONFIG_ARM_SCPI_POWER_DOMAIN is not set -+CONFIG_KPROBES=y -+CONFIG_JUMP_LABEL=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -+# CONFIG_SPARSEMEM_VMEMMAP is not set -+CONFIG_KSM=y -+CONFIG_TRANSPARENT_HUGEPAGE=y -+CONFIG_ZSMALLOC=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_XFRM_INTERFACE=y -+CONFIG_XFRM_STATISTICS=y -+CONFIG_NET_KEY=y -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_NET_IPGRE_DEMUX=y -+CONFIG_NET_IPVTI=y -+CONFIG_INET_ESP=y -+# CONFIG_INET_XFRM_MODE_BEET is not set -+CONFIG_INET_UDP_DIAG=y -+CONFIG_INET_DIAG_DESTROY=y -+CONFIG_TCP_CONG_ADVANCED=y -+# CONFIG_TCP_CONG_BIC is not set -+# CONFIG_TCP_CONG_WESTWOOD is not set -+# CONFIG_TCP_CONG_HTCP is not set -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_IPV6_ROUTE_INFO=y -+CONFIG_IPV6_OPTIMISTIC_DAD=y -+CONFIG_INET6_ESP=y -+CONFIG_INET6_IPCOMP=y -+CONFIG_IPV6_MIP6=y -+CONFIG_IPV6_VTI=y -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_NETFILTER=y -+CONFIG_NF_CONNTRACK=y -+CONFIG_NF_CONNTRACK_SECMARK=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_AMANDA=y -+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_CT=y -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -+CONFIG_NETFILTER_XT_TARGET_MARK=y -+CONFIG_NETFILTER_XT_TARGET_NFLOG=y -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -+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 -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y -+CONFIG_NETFILTER_XT_MATCH_HELPER=y -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -+CONFIG_NETFILTER_XT_MATCH_LENGTH=y -+CONFIG_NETFILTER_XT_MATCH_LIMIT=y -+CONFIG_NETFILTER_XT_MATCH_MAC=y -+CONFIG_NETFILTER_XT_MATCH_MARK=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 -+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -+CONFIG_NETFILTER_XT_MATCH_SOCKET=y -+CONFIG_NETFILTER_XT_MATCH_STATE=y -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y -+CONFIG_NETFILTER_XT_MATCH_STRING=y -+CONFIG_NETFILTER_XT_MATCH_TIME=y -+CONFIG_NETFILTER_XT_MATCH_U32=y -+CONFIG_IP_NF_IPTABLES=y -+CONFIG_IP_NF_MATCH_ECN=y -+CONFIG_IP_NF_MATCH_TTL=y -+CONFIG_IP_NF_FILTER=y -+CONFIG_IP_NF_TARGET_REJECT=y -+CONFIG_IP_NF_NAT=y -+CONFIG_IP_NF_TARGET_MASQUERADE=y -+CONFIG_IP_NF_TARGET_NETMAP=y -+CONFIG_IP_NF_TARGET_REDIRECT=y -+CONFIG_IP_NF_MANGLE=y -+CONFIG_IP_NF_RAW=y -+CONFIG_IP_NF_SECURITY=y -+CONFIG_IP_NF_ARPTABLES=y -+CONFIG_IP_NF_ARPFILTER=y -+CONFIG_IP_NF_ARP_MANGLE=y -+CONFIG_IP6_NF_IPTABLES=y -+CONFIG_IP6_NF_MATCH_RPFILTER=y -+CONFIG_IP6_NF_FILTER=y -+CONFIG_IP6_NF_TARGET_REJECT=y -+CONFIG_IP6_NF_MANGLE=y -+CONFIG_IP6_NF_RAW=y -+CONFIG_L2TP=y -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_HTB=y -+CONFIG_NET_SCH_NETEM=y -+CONFIG_NET_SCH_INGRESS=y -+CONFIG_NET_CLS_U32=y -+CONFIG_NET_CLS_BPF=y -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_U32=y -+CONFIG_NET_CLS_ACT=y -+CONFIG_VSOCKETS=y -+CONFIG_VIRTIO_VSOCKETS=y -+CONFIG_CFG80211=y -+# CONFIG_CFG80211_DEFAULT_PS is not set -+# CONFIG_CFG80211_CRDA_SUPPORT is not set -+CONFIG_MAC80211=y -+# CONFIG_MAC80211_RC_MINSTREL is not set -+CONFIG_RFKILL=y -+CONFIG_PCI=y -+CONFIG_PCI_HOST_GENERIC=y -+# CONFIG_UEVENT_HELPER is not set -+CONFIG_DEVTMPFS=y -+# CONFIG_ALLOW_DEV_COREDUMP is not set -+CONFIG_DEBUG_DEVRES=y -+CONFIG_OF_UNITTEST=y -+CONFIG_ZRAM=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=8192 -+CONFIG_VIRTIO_BLK=y -+CONFIG_UID_SYS_STATS=y -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_VIRTIO=y -+CONFIG_MD=y -+CONFIG_BLK_DEV_DM=y -+CONFIG_DM_CRYPT=y -+CONFIG_DM_UEVENT=y -+CONFIG_DM_VERITY=y -+CONFIG_DM_VERITY_AVB=y -+CONFIG_DM_VERITY_FEC=y -+CONFIG_DM_BOW=y -+CONFIG_NETDEVICES=y -+CONFIG_NETCONSOLE=y -+CONFIG_NETCONSOLE_DYNAMIC=y -+CONFIG_TUN=y -+CONFIG_VIRTIO_NET=y -+# CONFIG_ETHERNET is not set -+CONFIG_PHYLIB=y -+CONFIG_PPP=y -+CONFIG_PPP_BSDCOMP=y -+CONFIG_PPP_DEFLATE=y -+CONFIG_PPP_MPPE=y -+CONFIG_PPTP=y -+CONFIG_PPPOL2TP=y -+CONFIG_USB_RTL8152=y -+CONFIG_USB_USBNET=y -+# CONFIG_USB_NET_AX8817X is not set -+# CONFIG_USB_NET_AX88179_178A is not set -+# CONFIG_USB_NET_CDCETHER is not set -+# CONFIG_USB_NET_CDC_NCM is not set -+# CONFIG_USB_NET_NET1080 is not set -+# CONFIG_USB_NET_CDC_SUBSET is not set -+# CONFIG_USB_NET_ZAURUS is not set -+# CONFIG_WLAN_VENDOR_ADMTEK is not set -+# CONFIG_WLAN_VENDOR_ATH is not set -+# CONFIG_WLAN_VENDOR_ATMEL is not set -+# CONFIG_WLAN_VENDOR_BROADCOM is not set -+# CONFIG_WLAN_VENDOR_CISCO is not set -+# CONFIG_WLAN_VENDOR_INTEL is not set -+# CONFIG_WLAN_VENDOR_INTERSIL is not set -+# CONFIG_WLAN_VENDOR_MARVELL is not set -+# CONFIG_WLAN_VENDOR_MEDIATEK is not set -+# CONFIG_WLAN_VENDOR_RALINK is not set -+# CONFIG_WLAN_VENDOR_REALTEK is not set -+# CONFIG_WLAN_VENDOR_RSI is not set -+# CONFIG_WLAN_VENDOR_ST is not set -+# CONFIG_WLAN_VENDOR_TI is not set -+# CONFIG_WLAN_VENDOR_ZYDAS is not set -+# CONFIG_WLAN_VENDOR_QUANTENNA is not set -+CONFIG_VIRT_WIFI=y -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_INPUT_MOUSE is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_XPAD=y -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_INPUT_TABLET=y -+CONFIG_TABLET_USB_ACECAD=y -+CONFIG_TABLET_USB_AIPTEK=y -+CONFIG_TABLET_USB_GTCO=y -+CONFIG_TABLET_USB_HANWANG=y -+CONFIG_TABLET_USB_KBTAB=y -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_UINPUT=y -+# CONFIG_VT is not set -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVMEM is not set -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+# CONFIG_SERIAL_8250_EXAR is not set -+CONFIG_SERIAL_8250_NR_UARTS=48 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_MANY_PORTS=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+CONFIG_SERIAL_OF_PLATFORM=y -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_VIRTIO_CONSOLE=y -+CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_VIRTIO=y -+# CONFIG_HW_RANDOM_CAVIUM is not set -+# CONFIG_DEVPORT is not set -+# CONFIG_I2C_COMPAT is not set -+# CONFIG_I2C_HELPER_AUTO is not set -+# CONFIG_HWMON is not set -+CONFIG_THERMAL=y -+CONFIG_CPU_THERMAL=y -+CONFIG_MEDIA_SUPPORT=y -+# CONFIG_VGA_ARB is not set -+CONFIG_DRM=y -+# CONFIG_DRM_FBDEV_EMULATION is not set -+CONFIG_DRM_VIRTIO_GPU=y -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_HRTIMER=y -+# CONFIG_SND_SUPPORT_OLD_API is not set -+# CONFIG_SND_VERBOSE_PROCFS is not set -+# CONFIG_SND_DRIVERS is not set -+CONFIG_SND_INTEL8X0=y -+# CONFIG_SND_USB is not set -+CONFIG_HIDRAW=y -+CONFIG_UHID=y -+CONFIG_HID_A4TECH=y -+CONFIG_HID_ACRUX=y -+CONFIG_HID_ACRUX_FF=y -+CONFIG_HID_APPLE=y -+CONFIG_HID_BELKIN=y -+CONFIG_HID_CHERRY=y -+CONFIG_HID_CHICONY=y -+CONFIG_HID_PRODIKEYS=y -+CONFIG_HID_CYPRESS=y -+CONFIG_HID_DRAGONRISE=y -+CONFIG_DRAGONRISE_FF=y -+CONFIG_HID_EMS_FF=y -+CONFIG_HID_ELECOM=y -+CONFIG_HID_EZKEY=y -+CONFIG_HID_HOLTEK=y -+CONFIG_HID_KEYTOUCH=y -+CONFIG_HID_KYE=y -+CONFIG_HID_UCLOGIC=y -+CONFIG_HID_WALTOP=y -+CONFIG_HID_GYRATION=y -+CONFIG_HID_TWINHAN=y -+CONFIG_HID_KENSINGTON=y -+CONFIG_HID_LCPOWER=y -+CONFIG_HID_LOGITECH=y -+CONFIG_HID_LOGITECH_DJ=y -+CONFIG_LOGITECH_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_HID_MAGICMOUSE=y -+CONFIG_HID_MICROSOFT=y -+CONFIG_HID_MONTEREY=y -+CONFIG_HID_MULTITOUCH=y -+CONFIG_HID_NTRIG=y -+CONFIG_HID_ORTEK=y -+CONFIG_HID_PANTHERLORD=y -+CONFIG_PANTHERLORD_FF=y -+CONFIG_HID_PETALYNX=y -+CONFIG_HID_PICOLCD=y -+CONFIG_HID_PRIMAX=y -+CONFIG_HID_ROCCAT=y -+CONFIG_HID_SAITEK=y -+CONFIG_HID_SAMSUNG=y -+CONFIG_HID_SONY=y -+CONFIG_HID_SPEEDLINK=y -+CONFIG_HID_SUNPLUS=y -+CONFIG_HID_GREENASIA=y -+CONFIG_GREENASIA_FF=y -+CONFIG_HID_SMARTJOYPLUS=y -+CONFIG_SMARTJOYPLUS_FF=y -+CONFIG_HID_TIVO=y -+CONFIG_HID_TOPSEED=y -+CONFIG_HID_THRUSTMASTER=y -+CONFIG_HID_WACOM=y -+CONFIG_HID_WIIMOTE=y -+CONFIG_HID_ZEROPLUS=y -+CONFIG_HID_ZYDACRON=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_GADGET=y -+CONFIG_USB_CONFIGFS=y -+CONFIG_USB_CONFIGFS_UEVENT=y -+CONFIG_USB_CONFIGFS_F_FS=y -+CONFIG_USB_CONFIGFS_F_ACC=y -+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y -+CONFIG_USB_CONFIGFS_F_MIDI=y -+CONFIG_MMC=y -+# CONFIG_PWRSEQ_EMMC is not set -+# CONFIG_PWRSEQ_SIMPLE is not set -+# CONFIG_MMC_BLOCK is not set -+CONFIG_RTC_CLASS=y -+# CONFIG_RTC_SYSTOHC is not set -+CONFIG_RTC_DRV_PL030=y -+CONFIG_RTC_DRV_PL031=y -+CONFIG_VIRTIO_PCI=y -+# CONFIG_VIRTIO_PCI_LEGACY is not set -+CONFIG_VIRTIO_BALLOON=y -+CONFIG_VIRTIO_INPUT=y -+CONFIG_VIRTIO_MMIO=y -+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y -+CONFIG_STAGING=y -+CONFIG_ASHMEM=y -+CONFIG_ANDROID_VSOC=y -+CONFIG_ION=y -+CONFIG_COMMON_CLK_SCPI=y -+CONFIG_MAILBOX=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_ANDROID=y -+CONFIG_ANDROID_BINDER_IPC=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_F2FS_FS=y -+CONFIG_F2FS_FS_SECURITY=y -+CONFIG_FS_ENCRYPTION=y -+# CONFIG_DNOTIFY is not set -+CONFIG_QUOTA=y -+CONFIG_QFMT_V2=y -+CONFIG_FUSE_FS=y -+CONFIG_OVERLAY_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_PSTORE=y -+CONFIG_PSTORE_CONSOLE=y -+CONFIG_PSTORE_RAM=y -+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y -+CONFIG_SECURITY=y -+CONFIG_SECURITY_NETWORK=y -+CONFIG_LSM_MMAP_MIN_ADDR=65536 -+CONFIG_HARDENED_USERCOPY=y -+CONFIG_SECURITY_SELINUX=y -+CONFIG_CRYPTO_ADIANTUM=y -+CONFIG_CRYPTO_SHA512=y -+CONFIG_CRYPTO_LZ4=y -+CONFIG_CRYPTO_ZSTD=y -+CONFIG_CRYPTO_ANSI_CPRNG=y -+CONFIG_CRYPTO_DEV_VIRTIO=y -+CONFIG_XZ_DEC=y -+CONFIG_PRINTK_TIME=y -+CONFIG_DEBUG_INFO=y -+# CONFIG_ENABLE_MUST_CHECK is not set -+CONFIG_FRAME_WARN=1024 -+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -+CONFIG_MAGIC_SYSRQ=y -+CONFIG_DEBUG_STACK_USAGE=y -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_SOFTLOCKUP_DETECTOR=y -+# CONFIG_DETECT_HUNG_TASK is not set -+CONFIG_PANIC_TIMEOUT=5 -+CONFIG_SCHEDSTATS=y -+CONFIG_RCU_CPU_STALL_TIMEOUT=60 -+CONFIG_ENABLE_DEFAULT_TRACERS=y -+# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/patches/ANDROID-gki_defconfig-more-configs-for-partners.patch b/patches/ANDROID-gki_defconfig-more-configs-for-partners.patch deleted file mode 100644 index 108b3bcadb2b4914fc5e4cb530da32519dff0332..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-more-configs-for-partners.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Thu, 20 Jun 2019 14:30:05 -0700 -Subject: ANDROID: gki_defconfig: more configs for partners - -Bug: 135666008 -Signed-off-by: Tri Vo -Change-Id: I5e13f602bcacb416cace48f92f40689ebd3bb12e ---- - arch/arm64/configs/gki_defconfig | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 7eeafbecf1b9..3afe7f8d8310 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -10,6 +10,7 @@ CONFIG_IKCONFIG=y - CONFIG_IKCONFIG_PROC=y - CONFIG_MEMCG=y - CONFIG_MEMCG_SWAP=y -+CONFIG_BLK_CGROUP=y - CONFIG_RT_GROUP_SCHED=y - CONFIG_CGROUP_FREEZER=y - CONFIG_CPUSETS=y -@@ -61,12 +62,15 @@ CONFIG_ARM_SCMI_PROTOCOL=y - # CONFIG_ARM_SCMI_POWER_DOMAIN is not set - CONFIG_ARM_SCPI_PROTOCOL=y - # CONFIG_ARM_SCPI_POWER_DOMAIN is not set -+CONFIG_ARM64_CRYPTO=y -+CONFIG_CRYPTO_AES_ARM64=y - CONFIG_KPROBES=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set - # CONFIG_SPARSEMEM_VMEMMAP is not set -+CONFIG_MEMORY_HOTPLUG=y - CONFIG_TRANSPARENT_HUGEPAGE=y - CONFIG_CMA=y - CONFIG_CMA_AREAS=16 -@@ -82,6 +86,7 @@ CONFIG_INET=y - CONFIG_IP_MULTICAST=y - CONFIG_IP_ADVANCED_ROUTER=y - CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_PNP=y - CONFIG_NET_IPGRE_DEMUX=y - CONFIG_NET_IPVTI=y - CONFIG_INET_ESP=y -@@ -165,6 +170,7 @@ CONFIG_IP6_NF_TARGET_REJECT=y - CONFIG_IP6_NF_MANGLE=y - CONFIG_IP6_NF_RAW=y - CONFIG_L2TP=y -+CONFIG_BRIDGE=y - CONFIG_NET_SCHED=y - CONFIG_NET_SCH_HTB=y - CONFIG_NET_SCH_INGRESS=y -@@ -175,6 +181,7 @@ CONFIG_NET_EMATCH_U32=y - CONFIG_NET_CLS_ACT=y - CONFIG_VSOCKETS=y - CONFIG_VIRTIO_VSOCKETS=y -+CONFIG_BT=y - CONFIG_CFG80211=y - # CONFIG_CFG80211_DEFAULT_PS is not set - # CONFIG_CFG80211_CRDA_SUPPORT is not set -@@ -242,7 +249,6 @@ CONFIG_USB_USBNET=y - # CONFIG_WLAN_VENDOR_QUANTENNA is not set - CONFIG_VIRT_WIFI=y - CONFIG_INPUT_EVDEV=y --# CONFIG_INPUT_KEYBOARD is not set - # CONFIG_INPUT_MOUSE is not set - CONFIG_INPUT_JOYSTICK=y - CONFIG_INPUT_MISC=y -@@ -276,9 +282,11 @@ CONFIG_THERMAL=y - CONFIG_THERMAL_GOV_USER_SPACE=y - CONFIG_CPU_THERMAL=y - CONFIG_DEVFREQ_THERMAL=y -+CONFIG_MFD_SYSCON=y - CONFIG_REGULATOR=y - CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y - # CONFIG_VGA_ARB is not set - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set -@@ -334,8 +342,14 @@ CONFIG_ASHMEM=y - CONFIG_ANDROID_VSOC=y - CONFIG_ION=y - CONFIG_COMMON_CLK_SCPI=y -+CONFIG_HWSPINLOCK=y - CONFIG_MAILBOX=y - CONFIG_ARM_SMMU=y -+CONFIG_DEVFREQ_GOV_PERFORMANCE=y -+CONFIG_DEVFREQ_GOV_POWERSAVE=y -+CONFIG_DEVFREQ_GOV_USERSPACE=y -+CONFIG_DEVFREQ_GOV_PASSIVE=y -+CONFIG_EXTCON=y - CONFIG_PWM=y - CONFIG_GENERIC_PHY=y - CONFIG_ANDROID=y -@@ -355,6 +369,7 @@ CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_ECRYPT_FS=y - CONFIG_PSTORE=y - CONFIG_PSTORE_CONSOLE=y - CONFIG_PSTORE_RAM=y -@@ -364,11 +379,13 @@ CONFIG_SECURITY_NETWORK=y - CONFIG_HARDENED_USERCOPY=y - CONFIG_SECURITY_SELINUX=y - CONFIG_CRYPTO_ADIANTUM=y -+CONFIG_CRYPTO_MD4=y - CONFIG_CRYPTO_SHA512=y - CONFIG_CRYPTO_LZ4=y - CONFIG_CRYPTO_ZSTD=y - CONFIG_CRYPTO_ANSI_CPRNG=y - CONFIG_CRYPTO_DEV_VIRTIO=y -+CONFIG_CRC_CCITT=y - CONFIG_CRC8=y - CONFIG_XZ_DEC=y - CONFIG_DMA_CMA=y -@@ -384,3 +401,5 @@ CONFIG_SOFTLOCKUP_DETECTOR=y - CONFIG_PANIC_TIMEOUT=5 - CONFIG_SCHEDSTATS=y - # CONFIG_RUNTIME_TESTING_MENU is not set -+CONFIG_CORESIGHT=y -+CONFIG_CORESIGHT_STM=y diff --git a/patches/ANDROID-gki_defconfig-more-generic-configs-for-DLKMs.patch b/patches/ANDROID-gki_defconfig-more-generic-configs-for-DLKMs.patch deleted file mode 100644 index 5eccb244a5034f9e67ac585b08b951ee18f5dd76..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-more-generic-configs-for-DLKMs.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Sun, 19 May 2019 14:37:03 -0700 -Subject: ANDROID: gki_defconfig: more generic configs for DLKMs - -Test: boot arm64 cuttlefish -Signed-off-by: Tri Vo -Change-Id: I9f6380927f348d0a5e20d1acff2bef4331c3f591 ---- - arch/arm64/configs/gki_defconfig | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index b7ae05eb896e..04f531ef2511 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -192,6 +192,8 @@ CONFIG_UID_SYS_STATS=y - CONFIG_SCSI=y - # CONFIG_SCSI_PROC_FS is not set - CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_UFSHCD=y -+CONFIG_SCSI_UFSHCD_PLATFORM=y - CONFIG_SCSI_VIRTIO=y - CONFIG_MD=y - CONFIG_BLK_DEV_DM=y -@@ -266,6 +268,7 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_I2C_COMPAT is not set - # CONFIG_I2C_HELPER_AUTO is not set - CONFIG_SPMI=y -+CONFIG_PINCTRL=y - CONFIG_GPIOLIB=y - # CONFIG_HWMON is not set - CONFIG_THERMAL=y -@@ -290,6 +293,8 @@ CONFIG_SND_DYNAMIC_MINORS=y - # CONFIG_SND_VERBOSE_PROCFS is not set - # CONFIG_SND_DRIVERS is not set - CONFIG_SND_INTEL8X0=y -+CONFIG_SND_USB_AUDIO=y -+CONFIG_SND_SOC=y - CONFIG_HIDRAW=y - CONFIG_UHID=y - CONFIG_HID_APPLE=y -@@ -310,6 +315,8 @@ CONFIG_MMC=y - # CONFIG_PWRSEQ_EMMC is not set - # CONFIG_PWRSEQ_SIMPLE is not set - # CONFIG_MMC_BLOCK is not set -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_NEW_LEDS=y - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y -@@ -329,11 +336,12 @@ CONFIG_ANDROID_VSOC=y - CONFIG_ION=y - CONFIG_COMMON_CLK_SCPI=y - CONFIG_MAILBOX=y --CONFIG_PM_DEVFREQ=y -+CONFIG_ARM_SMMU=y - CONFIG_PWM=y - CONFIG_GENERIC_PHY=y - CONFIG_ANDROID=y - CONFIG_ANDROID_BINDER_IPC=y -+CONFIG_INTERCONNECT=y - CONFIG_EXT4_FS=y - CONFIG_EXT4_FS_SECURITY=y - CONFIG_F2FS_FS=y diff --git a/patches/ANDROID-gki_defconfig-remove-PWRSEQ_EMMC-and-PWRSEQ_SIMPLE.patch b/patches/ANDROID-gki_defconfig-remove-PWRSEQ_EMMC-and-PWRSEQ_SIMPLE.patch deleted file mode 100644 index e0854d1548678ceb406422842ad72c54993c5660..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-remove-PWRSEQ_EMMC-and-PWRSEQ_SIMPLE.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Thu, 17 Oct 2019 18:28:10 -0700 -Subject: ANDROID: gki_defconfig: remove PWRSEQ_EMMC and PWRSEQ_SIMPLE - -These modules are not required for GKI. - -Bug: 139431025 -Signed-off-by: Ram Muthiah -Change-Id: I9a82010eb326b0a336725037e0356a63a0c9f053 ---- - arch/x86/configs/gki_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 18c3429c7ede..949c449b9d1f 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -289,6 +289,8 @@ CONFIG_USB_CONFIGFS_F_ACC=y - CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y - CONFIG_USB_CONFIGFS_F_MIDI=y - CONFIG_MMC=m -+# CONFIG_PWRSEQ_EMMC is not set -+# CONFIG_PWRSEQ_SIMPLE is not set - CONFIG_NEW_LEDS=y - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y diff --git a/patches/ANDROID-gki_defconfig-remove-more-recommended-configs.patch b/patches/ANDROID-gki_defconfig-remove-more-recommended-configs.patch deleted file mode 100644 index 64dba450ab4ec3e2a788f491ebef372395824f7a..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-remove-more-recommended-configs.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Thu, 16 May 2019 09:57:57 -0700 -Subject: ANDROID: gki_defconfig: remove more recommended configs - -Disable following configs: -CONFIG_KSM -CONFIG_SGETMASK_SYSCALL -CONFIG_ARM64_SW_TTBR0_PAN - -Bug: 132717553 -Test: boot arm64 cuttlefish -Signed-off-by: Tri Vo -Change-Id: I2689515f3ddff10d6ad09c41ac5f4a0415922357 ---- - arch/arm64/configs/gki_defconfig | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 9c1086a740cf..b7ae05eb896e 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -22,7 +22,6 @@ CONFIG_BLK_DEV_INITRD=y - # CONFIG_RD_XZ is not set - # CONFIG_RD_LZO is not set - # CONFIG_RD_LZ4 is not set --CONFIG_SGETMASK_SYSCALL=y - # CONFIG_SYSFS_SYSCALL is not set - # CONFIG_FHANDLE is not set - CONFIG_KALLSYMS_ALL=y -@@ -40,7 +39,6 @@ CONFIG_ARMV8_DEPRECATED=y - CONFIG_SWP_EMULATION=y - CONFIG_CP15_BARRIER_EMULATION=y - CONFIG_SETEND_EMULATION=y --CONFIG_ARM64_SW_TTBR0_PAN=y - CONFIG_RANDOMIZE_BASE=y - # CONFIG_EFI is not set - CONFIG_COMPAT=y -@@ -67,7 +65,6 @@ CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set - # CONFIG_SPARSEMEM_VMEMMAP is not set --CONFIG_KSM=y - CONFIG_TRANSPARENT_HUGEPAGE=y - CONFIG_ZSMALLOC=y - CONFIG_NET=y diff --git a/patches/ANDROID-gki_defconfig-set-CONFIG_NR_CPUS-32.patch b/patches/ANDROID-gki_defconfig-set-CONFIG_NR_CPUS-32.patch deleted file mode 100644 index 0e8f93a6efe64d27848a79edcebf831d1cfb5cda..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-set-CONFIG_NR_CPUS-32.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Salyzyn -Date: Mon, 26 Aug 2019 07:56:13 -0700 -Subject: ANDROID: gki_defconfig: set CONFIG_NR_CPUS=32 - -Consensus is that CONFIG_NR_CPUS of 32 will deal with the future -products with a moderate engineering margin. - -Signed-off-by: Mark Salyzyn -Test: confirm value propagates to .config -Bug: 139693734 -Bug: 139406736 -Bug: 139692860 -Change-Id: I9687d37da254a612947398a45ae56ab01e676562 ---- - arch/arm64/configs/gki_defconfig | 1 + - arch/x86/configs/gki_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index b70d608b1ee6..2773a84fd939 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -37,6 +37,7 @@ CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y - CONFIG_SCHED_MC=y -+CONFIG_NR_CPUS=32 - CONFIG_SECCOMP=y - CONFIG_PARAVIRT=y - CONFIG_COMPAT=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index ae3d165a79c3..a1b2121bde8b 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -35,6 +35,7 @@ CONFIG_SLAB_FREELIST_RANDOM=y - CONFIG_SLAB_FREELIST_HARDENED=y - CONFIG_PROFILING=y - CONFIG_SMP=y -+CONFIG_NR_CPUS=32 - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set diff --git a/patches/ANDROID-gki_defconfig-sync-with-savedefconfig.patch b/patches/ANDROID-gki_defconfig-sync-with-savedefconfig.patch deleted file mode 100644 index 915681f4283628f06c3a4ed121b6cd0fe6e23d6c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-sync-with-savedefconfig.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Wed, 15 May 2019 15:47:18 -0700 -Subject: ANDROID: gki_defconfig: sync with savedefconfig - -Otherwise, build/build.sh will complain. - -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 4b17f0f9d0ae..9c1086a740cf 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -62,7 +62,6 @@ CONFIG_ARM_SCMI_PROTOCOL=y - CONFIG_ARM_SCPI_PROTOCOL=y - # CONFIG_ARM_SCPI_POWER_DOMAIN is not set - CONFIG_KPROBES=y --CONFIG_JUMP_LABEL=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y diff --git a/patches/ANDROID-gki_defconfig-workaround-to-enable-configs.patch b/patches/ANDROID-gki_defconfig-workaround-to-enable-configs.patch deleted file mode 100644 index 41435210f23af3cba5398b8d2bf5d2b8dbbd4277..0000000000000000000000000000000000000000 --- a/patches/ANDROID-gki_defconfig-workaround-to-enable-configs.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Thu, 20 Jun 2019 18:04:53 -0700 -Subject: ANDROID: gki_defconfig: workaround to enable configs - -We're interested in following configs, which can't be selected by -themselves: -CONFIG_GPIOLIB_IRQCHIP -CONFIG_GENERIC_PINCONF -CONFIG_PINCONF -CONFIG_PINMUX -CONFIG_GENERIC_TRACER -CONFIG_MFD_CORE - -As a workaround, enable configs that select the above: -CONFIG_PINCTRL_AMD -CONFIG_MFD_ACT8945A -CONFIG_FUNCTION_TRACER - -Bug: 135666008 -Bug: 135247530 -Change-Id: If348f54fc11ab2c35ed2241d50327d8ce3b0b72e -Signed-off-by: Tri Vo ---- - arch/arm64/configs/gki_defconfig | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 3afe7f8d8310..ec0566116066 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -276,12 +276,13 @@ CONFIG_HW_RANDOM_VIRTIO=y - # CONFIG_I2C_HELPER_AUTO is not set - CONFIG_SPMI=y - CONFIG_PINCTRL=y --CONFIG_GPIOLIB=y -+CONFIG_PINCTRL_AMD=y - # CONFIG_HWMON is not set - CONFIG_THERMAL=y - CONFIG_THERMAL_GOV_USER_SPACE=y - CONFIG_CPU_THERMAL=y - CONFIG_DEVFREQ_THERMAL=y -+CONFIG_MFD_ACT8945A=y - CONFIG_MFD_SYSCON=y - CONFIG_REGULATOR=y - CONFIG_MEDIA_SUPPORT=y -@@ -400,6 +401,7 @@ CONFIG_SOFTLOCKUP_DETECTOR=y - # CONFIG_DETECT_HUNG_TASK is not set - CONFIG_PANIC_TIMEOUT=5 - CONFIG_SCHEDSTATS=y -+CONFIG_FUNCTION_TRACER=y - # CONFIG_RUNTIME_TESTING_MENU is not set - CONFIG_CORESIGHT=y - CONFIG_CORESIGHT_STM=y diff --git a/patches/ANDROID-init-GKI-add-GKI_HACKS_TO_FIX.patch b/patches/ANDROID-init-GKI-add-GKI_HACKS_TO_FIX.patch deleted file mode 100644 index 2b4985a50f7ce4aa9e659bd52cad8b243c88c924..0000000000000000000000000000000000000000 --- a/patches/ANDROID-init-GKI-add-GKI_HACKS_TO_FIX.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Wed, 28 Aug 2019 15:52:02 -0700 -Subject: ANDROID: init: GKI: add GKI_HACKS_TO_FIX - -Add CONFIG_GKI_HACKS_TO_FIX as a mechanism to force -hidden configs to be selected for modules that will be built -separately. Also used to select drivers that need to be -modularized. - -As these issues are resolved upstream, the configs should -be removed from GKI_HACKS_TO_FIX - -Bug: 141266428 -Change-Id: Ic8b2a17cd3a389ac5ef999c8c79b5b5dfee73c8a -Signed-off-by: Todd Kjos ---- - init/Kconfig | 2 ++ - init/Kconfig.gki | 15 +++++++++++++++ - 2 files changed, 17 insertions(+) - create mode 100644 init/Kconfig.gki - -diff --git a/init/Kconfig b/init/Kconfig -index b4daad2bac23..e3f4463ac31c 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -2258,3 +2258,5 @@ config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE - # . - config ARCH_HAS_SYSCALL_WRAPPER - def_bool n -+ -+source "init/Kconfig.gki" -diff --git a/init/Kconfig.gki b/init/Kconfig.gki -new file mode 100644 -index 000000000000..fafcd618037d ---- /dev/null -+++ b/init/Kconfig.gki -@@ -0,0 +1,15 @@ -+# Atrocities needed for -+# a) building GKI modules in separate tree, or -+# b) building drivers that are not modularizable -+# -+# All of these should be reworked into an upstream solution -+# if possible. -+# -+config GKI_HACKS_TO_FIX -+ bool "GKI Dummy config options" -+ help -+ Dummy config option used to enable core functionality used by -+ modules that may not be selectable in this config. -+ -+ Unless you are building a GKI kernel to be used with modules -+ built from a different config, say N here. diff --git a/patches/ANDROID-init-GKI-enable-hidden-configs-for-DRM.patch b/patches/ANDROID-init-GKI-enable-hidden-configs-for-DRM.patch deleted file mode 100644 index 7ba6ac3ed05d88b066401d43f5c6feee9bbb8650..0000000000000000000000000000000000000000 --- a/patches/ANDROID-init-GKI-enable-hidden-configs-for-DRM.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Tue, 17 Sep 2019 14:36:04 -0700 -Subject: ANDROID: init: GKI: enable hidden configs for DRM - -Add hidden configs to GKI_HACKS_TO_FIX so they -are enabled for loadable DRM modules built -out-of-tree. - -Bug: 141266428 -Change-Id: Ibeda203afa54edc4f9a1daec9b4e8a928eb934fb -Signed-off-by: Todd Kjos ---- - init/Kconfig.gki | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/init/Kconfig.gki b/init/Kconfig.gki -index fafcd618037d..6c3f89bd8e25 100644 ---- a/init/Kconfig.gki -+++ b/init/Kconfig.gki -@@ -1,3 +1,14 @@ -+config GKI_HIDDEN_DRM_CONFIGS -+ bool "Hidden DRM configs needed for GKI" -+ select DRM_KMS_HELPER if (HAS_IOMEM && DRM) -+ select DRM_GEM_CMA_HELPER -+ select DRM_KMS_CMA_HELPER -+ select DRM_MIPI_DSI -+ help -+ Dummy config option used to enable hidden DRM configs. -+ These are normally selected implicitely when including a -+ DRM module, but for GKI, the modules are built out-of-tree. -+ - # Atrocities needed for - # a) building GKI modules in separate tree, or - # b) building drivers that are not modularizable -@@ -7,6 +18,7 @@ - # - config GKI_HACKS_TO_FIX - bool "GKI Dummy config options" -+ select GKI_HIDDEN_DRM_CONFIGS - help - Dummy config option used to enable core functionality used by - modules that may not be selectable in this config. diff --git a/patches/ANDROID-init-GKI-enable-hidden-configs-for-GPIO.patch b/patches/ANDROID-init-GKI-enable-hidden-configs-for-GPIO.patch deleted file mode 100644 index a5fa929f8c76ff38dd87071f4582f1dd52f3c233..0000000000000000000000000000000000000000 --- a/patches/ANDROID-init-GKI-enable-hidden-configs-for-GPIO.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Tue, 17 Sep 2019 16:19:15 -0700 -Subject: ANDROID: init: GKI: enable hidden configs for GPIO - -Add hidden configs to GKI_HACKS_TO_FIX so they are -enabled for loadable GPIO modules built out-of-tree - -Bug: 141266428 -Change-Id: Ie6e79921df67e86783f04cb869604c988656a034 -Signed-off-by: Todd Kjos ---- - init/Kconfig.gki | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/init/Kconfig.gki b/init/Kconfig.gki -index bbd5fac69355..5df8c67123ef 100644 ---- a/init/Kconfig.gki -+++ b/init/Kconfig.gki -@@ -25,6 +25,15 @@ config GKI_HIDDEN_SND_SOC_CONFIGS - These are normally selected implicitely when a module - that relies on it is configured. - -+config GKI_HIDDEN_GPIO_CONFIGS -+ bool "Hidden GPIO configs needed for GKI" -+ select PINCTRL_SINGLE if (PINCTRL && OF && HAS_IOMEM) -+ select GPIO_PL061 if (HAS_IOMEM && ARM_AMBA && GPIOLIB) -+ help -+ Dummy config option used to enable hidden GPIO configs. -+ These are normally selected implicitely when a module -+ that relies on it is configured. -+ - # Atrocities needed for - # a) building GKI modules in separate tree, or - # b) building drivers that are not modularizable -@@ -37,6 +46,7 @@ config GKI_HACKS_TO_FIX - select GKI_HIDDEN_DRM_CONFIGS - select GKI_HIDDEN_REGMAP_CONFIGS - select GKI_HIDDEN_SND_SOC_CONFIGS -+ select GKI_HIDDEN_GPIO_CONFIGS - help - Dummy config option used to enable core functionality used by - modules that may not be selectable in this config. diff --git a/patches/ANDROID-init-GKI-enable-hidden-configs-for-SND_SOC.patch b/patches/ANDROID-init-GKI-enable-hidden-configs-for-SND_SOC.patch deleted file mode 100644 index 1a3cf524a7eccaef8d3da071a8eaa815cad435b6..0000000000000000000000000000000000000000 --- a/patches/ANDROID-init-GKI-enable-hidden-configs-for-SND_SOC.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Tue, 17 Sep 2019 15:57:02 -0700 -Subject: ANDROID: init: GKI: enable hidden configs for SND_SOC - -Add hidden configs to GKI_HACKS_TO_FIX so they are -enabled for loadable SND_SOC modules built out-of-tree - -Bug: 141266428 -Change-Id: I4782b5bb401a76c647bac41258c1371762dace1c -Signed-off-by: Todd Kjos ---- - init/Kconfig.gki | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/init/Kconfig.gki b/init/Kconfig.gki -index 45966f3325b9..bbd5fac69355 100644 ---- a/init/Kconfig.gki -+++ b/init/Kconfig.gki -@@ -17,6 +17,14 @@ config GKI_HIDDEN_REGMAP_CONFIGS - These are normally selected implicitely when a module - that relies on it is configured. - -+config GKI_HIDDEN_SND_SOC_CONFIGS -+ bool "Hidden SND_SOC configs needed for GKI" -+ select SND_SOC_GENERIC_DMAENGINE_PCM if (SND_SOC && SND) -+ help -+ Dummy config option used to enable hidden SND_SOC configs. -+ These are normally selected implicitely when a module -+ that relies on it is configured. -+ - # Atrocities needed for - # a) building GKI modules in separate tree, or - # b) building drivers that are not modularizable -@@ -28,6 +36,7 @@ config GKI_HACKS_TO_FIX - bool "GKI Dummy config options" - select GKI_HIDDEN_DRM_CONFIGS - select GKI_HIDDEN_REGMAP_CONFIGS -+ select GKI_HIDDEN_SND_SOC_CONFIGS - help - Dummy config option used to enable core functionality used by - modules that may not be selectable in this config. diff --git a/patches/ANDROID-init-GKI-enable-hidden-configs-for-regmap.patch b/patches/ANDROID-init-GKI-enable-hidden-configs-for-regmap.patch deleted file mode 100644 index 51938cdb18dcf9d8a32652d5c3117adf34831f31..0000000000000000000000000000000000000000 --- a/patches/ANDROID-init-GKI-enable-hidden-configs-for-regmap.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Todd Kjos -Date: Tue, 17 Sep 2019 15:38:05 -0700 -Subject: ANDROID: init: GKI: enable hidden configs for regmap - -Add hidden configs to GKI_HACKS_TO_FIX so they are -enabled for loadable regmap modules built out-of-tree. - -Bug: 141266428 -Change-Id: I1dedb1fd6e26e36c12b28fcbbf0302f074547101 -Signed-off-by: Todd Kjos ---- - init/Kconfig.gki | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/init/Kconfig.gki b/init/Kconfig.gki -index 6c3f89bd8e25..45966f3325b9 100644 ---- a/init/Kconfig.gki -+++ b/init/Kconfig.gki -@@ -9,6 +9,14 @@ config GKI_HIDDEN_DRM_CONFIGS - These are normally selected implicitely when including a - DRM module, but for GKI, the modules are built out-of-tree. - -+config GKI_HIDDEN_REGMAP_CONFIGS -+ bool "Hidden Regmap configs needed for GKI" -+ select REGMAP_IRQ -+ help -+ Dummy config option used to enable hidden regmap configs. -+ These are normally selected implicitely when a module -+ that relies on it is configured. -+ - # Atrocities needed for - # a) building GKI modules in separate tree, or - # b) building drivers that are not modularizable -@@ -19,6 +27,7 @@ config GKI_HIDDEN_DRM_CONFIGS - config GKI_HACKS_TO_FIX - bool "GKI Dummy config options" - select GKI_HIDDEN_DRM_CONFIGS -+ select GKI_HIDDEN_REGMAP_CONFIGS - help - Dummy config option used to enable core functionality used by - modules that may not be selectable in this config. diff --git a/patches/ANDROID-label-cuttlefish-modules-for-gki.patch b/patches/ANDROID-label-cuttlefish-modules-for-gki.patch deleted file mode 100644 index f781df6df1910cf774acc4bd0d3a3866c2a7c5a3..0000000000000000000000000000000000000000 --- a/patches/ANDROID-label-cuttlefish-modules-for-gki.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Tue, 23 Jul 2019 15:19:58 -0700 -Subject: ANDROID: label cuttlefish modules for gki - -Bug: 138227143 -Test: Boot x86 cuttlefish and gki locally and via forrest -Change-Id: Iff0ea7f31f53897e16d753491e41c5f087abf77c -Signed-off-by: Ram Muthiah ---- - arch/arm64/configs/gki_defconfig | 3 ++- - arch/x86/configs/gki_defconfig | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 18e8f81cc0fb..43a1fea94c6a 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -1,3 +1,4 @@ -+CONFIG_LOCALVERSION="-mainline" - CONFIG_AUDIT=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y -@@ -319,7 +320,7 @@ CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_OTG=y - CONFIG_USB_GADGET=y --CONFIG_USB_DUMMY_HCD=y -+CONFIG_USB_DUMMY_HCD=m - CONFIG_USB_CONFIGFS=y - CONFIG_USB_CONFIGFS_UEVENT=y - CONFIG_USB_CONFIGFS_F_FS=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index eacebe96e422..4016f8be75c5 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -1,3 +1,4 @@ -+CONFIG_LOCALVERSION="-mainline" - CONFIG_AUDIT=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y -@@ -267,7 +268,7 @@ CONFIG_HID_MULTITOUCH=y - CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_GADGET=y --CONFIG_USB_DUMMY_HCD=y -+CONFIG_USB_DUMMY_HCD=m - CONFIG_USB_CONFIGFS=y - CONFIG_USB_CONFIGFS_UEVENT=y - CONFIG_USB_CONFIGFS_F_FS=y diff --git a/patches/ANDROID-mm-add-a-field-to-store-names-for-private-anonymous-memory.patch b/patches/ANDROID-mm-add-a-field-to-store-names-for-private-anonymous-memory.patch deleted file mode 100644 index 0e465172ef0679bce56926b8a8f464f2b193bab8..0000000000000000000000000000000000000000 --- a/patches/ANDROID-mm-add-a-field-to-store-names-for-private-anonymous-memory.patch +++ /dev/null @@ -1,644 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Colin Cross -Date: Tue, 27 Oct 2015 16:42:08 -0700 -Subject: ANDROID: mm: add a field to store names for private anonymous memory - -Userspace processes often have multiple allocators that each do -anonymous mmaps to get memory. When examining memory usage of -individual processes or systems as a whole, it is useful to be -able to break down the various heaps that were allocated by -each layer and examine their size, RSS, and physical memory -usage. - -This patch adds a user pointer to the shared union in -vm_area_struct that points to a null terminated string inside -the user process containing a name for the vma. vmas that -point to the same address will be merged, but vmas that -point to equivalent strings at different addresses will -not be merged. - -Userspace can set the name for a region of memory by calling -prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, len, (unsigned long)name); -Setting the name to NULL clears it. - -The names of named anonymous vmas are shown in /proc/pid/maps -as [anon:] and in /proc/pid/smaps in a new "Name" field -that is only present for named vmas. If the userspace pointer -is no longer valid all or part of the name will be replaced -with "". - -The idea to store a userspace pointer to reduce the complexity -within mm (at the expense of the complexity of reading -/proc/pid/mem) came from Dave Hansen. This results in no -runtime overhead in the mm subsystem other than comparing -the anon_name pointers when considering vma merging. The pointer -is stored in a union with fieds that are only used on file-backed -mappings, so it does not increase memory usage. - -Includes fix from Jed Davis for typo in -prctl_set_vma_anon_name, which could attempt to set the name -across two vmas at the same time due to a typo, which might -corrupt the vma list. Fix it to use tmp instead of end to limit -the name setting to a single vma at a time. - -Bug: 120441514 -Change-Id: I9aa7b6b5ef536cd780599ba4e2fba8ceebe8b59f -Signed-off-by: Dmitry Shmidt -[AmitP: Fix get_user_pages_remote() call to align with upstream commit - 5b56d49fc31d ("mm: add locked parameter to get_user_pages_remote()")] -Signed-off-by: Amit Pundir ---- - Documentation/filesystems/proc.txt | 6 ++ - fs/proc/task_mmu.c | 64 +++++++++++- - fs/userfaultfd.c | 9 +- - include/linux/mm.h | 2 +- - include/linux/mm_types.h | 24 ++++- - include/uapi/linux/prctl.h | 3 + - kernel/sys.c | 152 +++++++++++++++++++++++++++++ - mm/madvise.c | 2 +- - mm/mempolicy.c | 3 +- - mm/mlock.c | 2 +- - mm/mmap.c | 39 +++++--- - mm/mprotect.c | 2 +- - 12 files changed, 280 insertions(+), 28 deletions(-) - -diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt -index 99ca040e3f90..4579d1452f89 100644 ---- a/Documentation/filesystems/proc.txt -+++ b/Documentation/filesystems/proc.txt -@@ -415,6 +415,8 @@ is not associated with a file: - [stack] = the stack of the main process - [vdso] = the "virtual dynamic shared object", - the kernel system call handler -+ [anon:] = an anonymous mapping that has been -+ named by userspace - - or if empty, the mapping is anonymous. - -@@ -447,6 +449,7 @@ MMUPageSize: 4 kB - Locked: 0 kB - THPeligible: 0 - VmFlags: rd ex mr mw me dw -+Name: name from userspace - - The first of these lines shows the same information as is displayed for the - mapping in /proc/PID/maps. Following lines show the size of the mapping -@@ -526,6 +529,9 @@ be vanished or the reverse -- new added. Interpretation of their meaning - might change in future as well. So each consumer of these flags has to - follow each specific kernel version for the exact semantic. - -+The "Name" field will only be present on a mapping that has been named by -+userspace, and will show the name passed in by userspace. -+ - This file is only present if the CONFIG_MMU kernel configuration option is - enabled. - -diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 9442631fd4af..1ce1cb08a5d3 100644 ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -123,6 +123,56 @@ static void release_task_mempolicy(struct proc_maps_private *priv) - } - #endif - -+static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma) -+{ -+ const char __user *name = vma_get_anon_name(vma); -+ struct mm_struct *mm = vma->vm_mm; -+ -+ unsigned long page_start_vaddr; -+ unsigned long page_offset; -+ unsigned long num_pages; -+ unsigned long max_len = NAME_MAX; -+ int i; -+ -+ page_start_vaddr = (unsigned long)name & PAGE_MASK; -+ page_offset = (unsigned long)name - page_start_vaddr; -+ num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE); -+ -+ seq_puts(m, "[anon:"); -+ -+ for (i = 0; i < num_pages; i++) { -+ int len; -+ int write_len; -+ const char *kaddr; -+ long pages_pinned; -+ struct page *page; -+ -+ pages_pinned = get_user_pages_remote(current, mm, -+ page_start_vaddr, 1, 0, &page, NULL, NULL); -+ if (pages_pinned < 1) { -+ seq_puts(m, "]"); -+ return; -+ } -+ -+ kaddr = (const char *)kmap(page); -+ len = min(max_len, PAGE_SIZE - page_offset); -+ write_len = strnlen(kaddr + page_offset, len); -+ seq_write(m, kaddr + page_offset, write_len); -+ kunmap(page); -+ put_page(page); -+ -+ /* if strnlen hit a null terminator then we're done */ -+ if (write_len != len) -+ break; -+ -+ max_len -= len; -+ page_offset = 0; -+ page_start_vaddr += PAGE_SIZE; -+ } -+ -+ seq_putc(m, ']'); -+} -+ - static void vma_stop(struct proc_maps_private *priv) - { - struct mm_struct *mm = priv->mm; -@@ -348,8 +398,15 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) - goto done; - } - -- if (is_stack(vma)) -+ if (is_stack(vma)) { - name = "[stack]"; -+ goto done; -+ } -+ -+ if (vma_get_anon_name(vma)) { -+ seq_pad(m, ' '); -+ seq_print_vma_name(m, vma); -+ } - } - - done: -@@ -832,6 +889,11 @@ static int show_smap(struct seq_file *m, void *v) - smap_gather_stats(vma, &mss); - - show_map_vma(m, vma); -+ if (vma_get_anon_name(vma)) { -+ seq_puts(m, "Name: "); -+ seq_print_vma_name(m, vma); -+ seq_putc(m, '\n'); -+ } - - SEQ_PUT_DEC("Size: ", vma->vm_end - vma->vm_start); - SEQ_PUT_DEC(" kB\nKernelPageSize: ", vma_kernel_pagesize(vma)); -diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c -index f9fd18670e22..fc08951daa62 100644 ---- a/fs/userfaultfd.c -+++ b/fs/userfaultfd.c -@@ -912,7 +912,8 @@ static int userfaultfd_release(struct inode *inode, struct file *file) - new_flags, vma->anon_vma, - vma->vm_file, vma->vm_pgoff, - vma_policy(vma), -- NULL_VM_UFFD_CTX); -+ NULL_VM_UFFD_CTX, -+ vma_get_anon_name(vma)); - if (prev) - vma = prev; - else -@@ -1464,7 +1465,8 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, - prev = vma_merge(mm, prev, start, vma_end, new_flags, - vma->anon_vma, vma->vm_file, vma->vm_pgoff, - vma_policy(vma), -- ((struct vm_userfaultfd_ctx){ ctx })); -+ ((struct vm_userfaultfd_ctx){ ctx }), -+ vma_get_anon_name(vma)); - if (prev) { - vma = prev; - goto next; -@@ -1626,7 +1628,8 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx, - prev = vma_merge(mm, prev, start, vma_end, new_flags, - vma->anon_vma, vma->vm_file, vma->vm_pgoff, - vma_policy(vma), -- NULL_VM_UFFD_CTX); -+ NULL_VM_UFFD_CTX, -+ vma_get_anon_name(vma)); - if (prev) { - vma = prev; - goto next; -diff --git a/include/linux/mm.h b/include/linux/mm.h -index cc292273e6ba..3d0c800fe574 100644 ---- a/include/linux/mm.h -+++ b/include/linux/mm.h -@@ -2278,7 +2278,7 @@ static inline int vma_adjust(struct vm_area_struct *vma, unsigned long start, - extern struct vm_area_struct *vma_merge(struct mm_struct *, - struct vm_area_struct *prev, unsigned long addr, unsigned long end, - unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t, -- struct mempolicy *, struct vm_userfaultfd_ctx); -+ struct mempolicy *, struct vm_userfaultfd_ctx, const char __user *); - extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *); - extern int __split_vma(struct mm_struct *, struct vm_area_struct *, - unsigned long addr, int new_below); -diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index 2222fa795284..7812502ce65a 100644 ---- a/include/linux/mm_types.h -+++ b/include/linux/mm_types.h -@@ -313,11 +313,18 @@ struct vm_area_struct { - /* - * For areas with an address space and backing store, - * linkage into the address_space->i_mmap interval tree. -+ * -+ * For private anonymous mappings, a pointer to a null terminated string -+ * in the user process containing the name given to the vma, or NULL -+ * if unnamed. - */ -- struct { -- struct rb_node rb; -- unsigned long rb_subtree_last; -- } shared; -+ union { -+ struct { -+ struct rb_node rb; -+ unsigned long rb_subtree_last; -+ } shared; -+ const char __user *anon_name; -+ }; - - /* - * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma -@@ -749,4 +756,13 @@ typedef struct { - unsigned long val; - } swp_entry_t; - -+/* Return the name for an anonymous mapping or NULL for a file-backed mapping */ -+static inline const char __user *vma_get_anon_name(struct vm_area_struct *vma) -+{ -+ if (vma->vm_file) -+ return NULL; -+ -+ return vma->anon_name; -+} -+ - #endif /* _LINUX_MM_TYPES_H */ -diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h -index 7da1b37b27aa..bc4a5d963ac8 100644 ---- a/include/uapi/linux/prctl.h -+++ b/include/uapi/linux/prctl.h -@@ -234,4 +234,7 @@ struct prctl_mm_map { - #define PR_GET_TAGGED_ADDR_CTRL 56 - # define PR_TAGGED_ADDR_ENABLE (1UL << 0) - -+#define PR_SET_VMA 0x53564d41 -+# define PR_SET_VMA_ANON_NAME 0 -+ - #endif /* _LINUX_PRCTL_H */ -diff --git a/kernel/sys.c b/kernel/sys.c -index a611d1d58c7d..70660867f50e 100644 ---- a/kernel/sys.c -+++ b/kernel/sys.c -@@ -42,6 +42,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -2259,6 +2261,153 @@ int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which, - return -EINVAL; - } - -+#ifdef CONFIG_MMU -+static int prctl_update_vma_anon_name(struct vm_area_struct *vma, -+ struct vm_area_struct **prev, -+ unsigned long start, unsigned long end, -+ const char __user *name_addr) -+{ -+ struct mm_struct *mm = vma->vm_mm; -+ int error = 0; -+ pgoff_t pgoff; -+ -+ if (name_addr == vma_get_anon_name(vma)) { -+ *prev = vma; -+ goto out; -+ } -+ -+ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); -+ *prev = vma_merge(mm, *prev, start, end, vma->vm_flags, vma->anon_vma, -+ vma->vm_file, pgoff, vma_policy(vma), -+ vma->vm_userfaultfd_ctx, name_addr); -+ if (*prev) { -+ vma = *prev; -+ goto success; -+ } -+ -+ *prev = vma; -+ -+ if (start != vma->vm_start) { -+ error = split_vma(mm, vma, start, 1); -+ if (error) -+ goto out; -+ } -+ -+ if (end != vma->vm_end) { -+ error = split_vma(mm, vma, end, 0); -+ if (error) -+ goto out; -+ } -+ -+success: -+ if (!vma->vm_file) -+ vma->anon_name = name_addr; -+ -+out: -+ if (error == -ENOMEM) -+ error = -EAGAIN; -+ return error; -+} -+ -+static int prctl_set_vma_anon_name(unsigned long start, unsigned long end, -+ unsigned long arg) -+{ -+ unsigned long tmp; -+ struct vm_area_struct *vma, *prev; -+ int unmapped_error = 0; -+ int error = -EINVAL; -+ -+ /* -+ * If the interval [start,end) covers some unmapped address -+ * ranges, just ignore them, but return -ENOMEM at the end. -+ * - this matches the handling in madvise. -+ */ -+ vma = find_vma_prev(current->mm, start, &prev); -+ if (vma && start > vma->vm_start) -+ prev = vma; -+ -+ for (;;) { -+ /* Still start < end. */ -+ error = -ENOMEM; -+ if (!vma) -+ return error; -+ -+ /* Here start < (end|vma->vm_end). */ -+ if (start < vma->vm_start) { -+ unmapped_error = -ENOMEM; -+ start = vma->vm_start; -+ if (start >= end) -+ return error; -+ } -+ -+ /* Here vma->vm_start <= start < (end|vma->vm_end) */ -+ tmp = vma->vm_end; -+ if (end < tmp) -+ tmp = end; -+ -+ /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */ -+ error = prctl_update_vma_anon_name(vma, &prev, start, tmp, -+ (const char __user *)arg); -+ if (error) -+ return error; -+ start = tmp; -+ if (prev && start < prev->vm_end) -+ start = prev->vm_end; -+ error = unmapped_error; -+ if (start >= end) -+ return error; -+ if (prev) -+ vma = prev->vm_next; -+ else /* madvise_remove dropped mmap_sem */ -+ vma = find_vma(current->mm, start); -+ } -+} -+ -+static int prctl_set_vma(unsigned long opt, unsigned long start, -+ unsigned long len_in, unsigned long arg) -+{ -+ struct mm_struct *mm = current->mm; -+ int error; -+ unsigned long len; -+ unsigned long end; -+ -+ if (start & ~PAGE_MASK) -+ return -EINVAL; -+ len = (len_in + ~PAGE_MASK) & PAGE_MASK; -+ -+ /* Check to see whether len was rounded up from small -ve to zero */ -+ if (len_in && !len) -+ return -EINVAL; -+ -+ end = start + len; -+ if (end < start) -+ return -EINVAL; -+ -+ if (end == start) -+ return 0; -+ -+ down_write(&mm->mmap_sem); -+ -+ switch (opt) { -+ case PR_SET_VMA_ANON_NAME: -+ error = prctl_set_vma_anon_name(start, end, arg); -+ break; -+ default: -+ error = -EINVAL; -+ } -+ -+ up_write(&mm->mmap_sem); -+ -+ return error; -+} -+#else /* CONFIG_MMU */ -+static int prctl_set_vma(unsigned long opt, unsigned long start, -+ unsigned long len_in, unsigned long arg) -+{ -+ return -EINVAL; -+} -+#endif -+ - SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, - unsigned long, arg4, unsigned long, arg5) - { -@@ -2471,6 +2620,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, - return -EINVAL; - error = arch_prctl_spec_ctrl_set(me, arg2, arg3); - break; -+ case PR_SET_VMA: -+ error = prctl_set_vma(arg2, arg3, arg4, arg5); -+ break; - case PR_PAC_RESET_KEYS: - if (arg3 || arg4 || arg5) - return -EINVAL; -diff --git a/mm/madvise.c b/mm/madvise.c -index 2be9f3fdb05e..1cfc273b7e25 100644 ---- a/mm/madvise.c -+++ b/mm/madvise.c -@@ -134,7 +134,7 @@ static long madvise_behavior(struct vm_area_struct *vma, - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma, - vma->vm_file, pgoff, vma_policy(vma), -- vma->vm_userfaultfd_ctx); -+ vma->vm_userfaultfd_ctx, vma_get_anon_name(vma)); - if (*prev) { - vma = *prev; - goto success; -diff --git a/mm/mempolicy.c b/mm/mempolicy.c -index 4ae967bcf954..9271109b7d3a 100644 ---- a/mm/mempolicy.c -+++ b/mm/mempolicy.c -@@ -757,7 +757,8 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, - ((vmstart - vma->vm_start) >> PAGE_SHIFT); - prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags, - vma->anon_vma, vma->vm_file, pgoff, -- new_pol, vma->vm_userfaultfd_ctx); -+ new_pol, vma->vm_userfaultfd_ctx, -+ vma_get_anon_name(vma)); - if (prev) { - vma = prev; - next = vma->vm_next; -diff --git a/mm/mlock.c b/mm/mlock.c -index a72c1eeded77..646acba3045b 100644 ---- a/mm/mlock.c -+++ b/mm/mlock.c -@@ -535,7 +535,7 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev, - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma, - vma->vm_file, pgoff, vma_policy(vma), -- vma->vm_userfaultfd_ctx); -+ vma->vm_userfaultfd_ctx, vma_get_anon_name(vma)); - if (*prev) { - vma = *prev; - goto success; -diff --git a/mm/mmap.c b/mm/mmap.c -index a7d8c84d19b7..fa75b568d481 100644 ---- a/mm/mmap.c -+++ b/mm/mmap.c -@@ -1017,7 +1017,8 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, - */ - static inline int is_mergeable_vma(struct vm_area_struct *vma, - struct file *file, unsigned long vm_flags, -- struct vm_userfaultfd_ctx vm_userfaultfd_ctx) -+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx, -+ const char __user *anon_name) - { - /* - * VM_SOFTDIRTY should not prevent from VMA merging, if we -@@ -1035,6 +1036,8 @@ static inline int is_mergeable_vma(struct vm_area_struct *vma, - return 0; - if (!is_mergeable_vm_userfaultfd_ctx(vma, vm_userfaultfd_ctx)) - return 0; -+ if (vma_get_anon_name(vma) != anon_name) -+ return 0; - return 1; - } - -@@ -1067,9 +1070,10 @@ static int - can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, - pgoff_t vm_pgoff, -- struct vm_userfaultfd_ctx vm_userfaultfd_ctx) -+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx, -+ const char __user *anon_name) - { -- if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) && -+ if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx, anon_name) && - is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { - if (vma->vm_pgoff == vm_pgoff) - return 1; -@@ -1088,9 +1092,10 @@ static int - can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, - pgoff_t vm_pgoff, -- struct vm_userfaultfd_ctx vm_userfaultfd_ctx) -+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx, -+ const char __user *anon_name) - { -- if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) && -+ if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx, anon_name) && - is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { - pgoff_t vm_pglen; - vm_pglen = vma_pages(vma); -@@ -1101,9 +1106,9 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, - } - - /* -- * Given a mapping request (addr,end,vm_flags,file,pgoff), figure out -- * whether that can be merged with its predecessor or its successor. -- * Or both (it neatly fills a hole). -+ * Given a mapping request (addr,end,vm_flags,file,pgoff,anon_name), -+ * figure out whether that can be merged with its predecessor or its -+ * successor. Or both (it neatly fills a hole). - * - * In most cases - when called for mmap, brk or mremap - [addr,end) is - * certain not to be mapped by the time vma_merge is called; but when -@@ -1145,7 +1150,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, - unsigned long end, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, - pgoff_t pgoff, struct mempolicy *policy, -- struct vm_userfaultfd_ctx vm_userfaultfd_ctx) -+ struct vm_userfaultfd_ctx vm_userfaultfd_ctx, -+ const char __user *anon_name) - { - pgoff_t pglen = (end - addr) >> PAGE_SHIFT; - struct vm_area_struct *area, *next; -@@ -1178,7 +1184,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, - mpol_equal(vma_policy(prev), policy) && - can_vma_merge_after(prev, vm_flags, - anon_vma, file, pgoff, -- vm_userfaultfd_ctx)) { -+ vm_userfaultfd_ctx, -+ anon_name)) { - /* - * OK, it can. Can we now merge in the successor as well? - */ -@@ -1187,7 +1194,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, - can_vma_merge_before(next, vm_flags, - anon_vma, file, - pgoff+pglen, -- vm_userfaultfd_ctx) && -+ vm_userfaultfd_ctx, -+ anon_name) && - is_mergeable_anon_vma(prev->anon_vma, - next->anon_vma, NULL)) { - /* cases 1, 6 */ -@@ -1210,7 +1218,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, - mpol_equal(policy, vma_policy(next)) && - can_vma_merge_before(next, vm_flags, - anon_vma, file, pgoff+pglen, -- vm_userfaultfd_ctx)) { -+ vm_userfaultfd_ctx, -+ anon_name)) { - if (prev && addr < prev->vm_end) /* case 4 */ - err = __vma_adjust(prev, prev->vm_start, - addr, prev->vm_pgoff, NULL, next); -@@ -1764,7 +1773,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, - * Can we just expand an old mapping? - */ - vma = vma_merge(mm, prev, addr, addr + len, vm_flags, -- NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX); -+ NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX, NULL); - if (vma) - goto out; - -@@ -3041,7 +3050,7 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla - - /* Can we just expand an old private anonymous mapping? */ - vma = vma_merge(mm, prev, addr, addr + len, flags, -- NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX); -+ NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX, NULL); - if (vma) - goto out; - -@@ -3239,7 +3248,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, - return NULL; /* should never get here */ - new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), -- vma->vm_userfaultfd_ctx); -+ vma->vm_userfaultfd_ctx, vma_get_anon_name(vma)); - if (new_vma) { - /* - * Source vma may have been merged into new_vma -diff --git a/mm/mprotect.c b/mm/mprotect.c -index 7967825f6d33..3cad0a44df91 100644 ---- a/mm/mprotect.c -+++ b/mm/mprotect.c -@@ -394,7 +394,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - *pprev = vma_merge(mm, *pprev, start, end, newflags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), -- vma->vm_userfaultfd_ctx); -+ vma->vm_userfaultfd_ctx, vma_get_anon_name(vma)); - if (*pprev) { - vma = *pprev; - VM_WARN_ON((vma->vm_flags ^ newflags) & ~VM_SOFTDIRTY); diff --git a/patches/ANDROID-mmc-core-Add-ignore-mmc-pm-notify-functionality.patch b/patches/ANDROID-mmc-core-Add-ignore-mmc-pm-notify-functionality.patch deleted file mode 100644 index 20e2983675e357e41a93c96497e0510a0414c61a..0000000000000000000000000000000000000000 --- a/patches/ANDROID-mmc-core-Add-ignore-mmc-pm-notify-functionality.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dmitry Shmidt -Date: Thu, 7 Oct 2010 14:39:16 -0700 -Subject: ANDROID: mmc: core: Add "ignore mmc pm notify" functionality - -Used to prevent remounting MMC on suspend/resume. - -Bug: 120441127 -Change-Id: I20821a82831b07ca037973d5d92e832372c6b583 -Signed-off-by: Dmitry Shmidt ---- - drivers/mmc/core/host.c | 6 ++++-- - include/linux/mmc/pm.h | 1 + - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c -index 105b7a7c0251..faa6975d436c 100644 ---- a/drivers/mmc/core/host.c -+++ b/drivers/mmc/core/host.c -@@ -480,7 +480,8 @@ int mmc_add_host(struct mmc_host *host) - #endif - - mmc_start_host(host); -- mmc_register_pm_notifier(host); -+ if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) -+ mmc_register_pm_notifier(host); - - return 0; - } -@@ -497,7 +498,8 @@ EXPORT_SYMBOL(mmc_add_host); - */ - void mmc_remove_host(struct mmc_host *host) - { -- mmc_unregister_pm_notifier(host); -+ if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) -+ mmc_unregister_pm_notifier(host); - mmc_stop_host(host); - - #ifdef CONFIG_DEBUG_FS -diff --git a/include/linux/mmc/pm.h b/include/linux/mmc/pm.h -index 3549f8045784..1d554b858086 100644 ---- a/include/linux/mmc/pm.h -+++ b/include/linux/mmc/pm.h -@@ -23,5 +23,6 @@ typedef unsigned int mmc_pm_flag_t; - - #define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */ - #define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */ -+#define MMC_PM_IGNORE_PM_NOTIFY (1 << 2) /* ignore mmc pm notify */ - - #endif /* LINUX_MMC_PM_H */ diff --git a/patches/ANDROID-mnt-Add-filesystem-private-data-to-mount-points.patch b/patches/ANDROID-mnt-Add-filesystem-private-data-to-mount-points.patch deleted file mode 100644 index 2a45e89f56a68f92898f647b85d89545efe6e6ae..0000000000000000000000000000000000000000 --- a/patches/ANDROID-mnt-Add-filesystem-private-data-to-mount-points.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Wed, 26 Oct 2016 15:29:51 -0700 -Subject: ANDROID: mnt: Add filesystem private data to mount points - -This starts to add private data associated directly -to mount points. The intent is to give filesystems -a sense of where they have come from, as a means of -letting a filesystem take different actions based on -this information. - -Bug: 62094374 -Bug: 120446149 -Bug: 122428178 -Change-Id: Ie769d7b3bb2f5972afe05c1bf16cf88c91647ab2 -Signed-off-by: Daniel Rosenberg -[astrachan: Folded 89a54ed3bf68 ("ANDROID: mnt: Fix next_descendent") - into this patch] -[drosen: Folded 138993ea820 ("Android: mnt: Propagate remount - correctly") into this patch, integrated fs_context things - Now has update_mnt_data instead of needing remount2 -Signed-off-by: Alistair Strachan ---- - fs/namespace.c | 28 +++++++++++++++++++++++++++- - fs/pnode.c | 16 ++++++++++++++++ - fs/pnode.h | 1 + - include/linux/fs.h | 4 ++++ - include/linux/mount.h | 1 + - 5 files changed, 49 insertions(+), 1 deletion(-) - -diff --git a/fs/namespace.c b/fs/namespace.c -index fe0e9e1410fe..4ec782ed6069 100644 ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -198,6 +198,7 @@ static struct mount *alloc_vfsmnt(const char *name) - mnt->mnt_count = 1; - mnt->mnt_writers = 0; - #endif -+ mnt->mnt.data = NULL; - - INIT_HLIST_NODE(&mnt->mnt_hash); - INIT_LIST_HEAD(&mnt->mnt_child); -@@ -547,6 +548,7 @@ int sb_prepare_remount_readonly(struct super_block *sb) - - static void free_vfsmnt(struct mount *mnt) - { -+ kfree(mnt->mnt.data); - kfree_const(mnt->mnt_devname); - #ifdef CONFIG_SMP - free_percpu(mnt->mnt_pcp); -@@ -941,6 +943,15 @@ struct vfsmount *vfs_create_mount(struct fs_context *fc) - if (!mnt) - return ERR_PTR(-ENOMEM); - -+ if (fc->fs_type->alloc_mnt_data) { -+ mnt->mnt.data = fc->fs_type->alloc_mnt_data(); -+ if (!mnt->mnt.data) { -+ mnt_free_id(mnt); -+ free_vfsmnt(mnt); -+ return ERR_PTR(-ENOMEM); -+ } -+ fc->root->d_sb->s_op->update_mnt_data(mnt->mnt.data, fc); -+ } - if (fc->sb_flags & SB_KERNMOUNT) - mnt->mnt.mnt_flags = MNT_INTERNAL; - -@@ -1024,6 +1035,14 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, - if (!mnt) - return ERR_PTR(-ENOMEM); - -+ if (sb->s_op->clone_mnt_data) { -+ mnt->mnt.data = sb->s_op->clone_mnt_data(old->mnt.data); -+ if (!mnt->mnt.data) { -+ err = -ENOMEM; -+ goto out_free; -+ } -+ } -+ - if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE)) - mnt->mnt_group_id = 0; /* not a peer of original */ - else -@@ -2549,8 +2568,15 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, - err = -EPERM; - if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) { - err = reconfigure_super(fc); -- if (!err) -+ if (!err) { -+ sb->s_op->update_mnt_data(mnt->mnt.data, fc); - set_mount_attributes(mnt, mnt_flags); -+ namespace_lock(); -+ lock_mount_hash(); -+ propagate_remount(mnt); -+ unlock_mount_hash(); -+ namespace_unlock(); -+ } - } - up_write(&sb->s_umount); - } -diff --git a/fs/pnode.c b/fs/pnode.c -index 49f6d7ff2139..16b2d165b5e9 100644 ---- a/fs/pnode.c -+++ b/fs/pnode.c -@@ -601,3 +601,19 @@ int propagate_umount(struct list_head *list) - - return 0; - } -+ -+void propagate_remount(struct mount *mnt) -+{ -+ struct mount *parent = mnt->mnt_parent; -+ struct mount *p = mnt, *m; -+ struct super_block *sb = mnt->mnt.mnt_sb; -+ -+ if (!sb->s_op->copy_mnt_data) -+ return; -+ for (p = propagation_next(parent, parent); p; -+ p = propagation_next(p, parent)) { -+ m = __lookup_mnt(&p->mnt, mnt->mnt_mountpoint); -+ if (m) -+ sb->s_op->copy_mnt_data(m->mnt.data, mnt->mnt.data); -+ } -+} -diff --git a/fs/pnode.h b/fs/pnode.h -index 49a058c73e4c..a95e519b77bf 100644 ---- a/fs/pnode.h -+++ b/fs/pnode.h -@@ -42,6 +42,7 @@ int propagate_mnt(struct mount *, struct mountpoint *, struct mount *, - int propagate_umount(struct list_head *); - int propagate_mount_busy(struct mount *, int); - void propagate_mount_unlock(struct mount *); -+void propagate_remount(struct mount *); - void mnt_release_group_id(struct mount *); - int get_dominating_id(struct mount *mnt, const struct path *root); - unsigned int mnt_get_count(struct mount *mnt); -diff --git a/include/linux/fs.h b/include/linux/fs.h -index eccf96ceef3b..f3fa2a711152 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1962,6 +1962,9 @@ struct super_operations { - int (*unfreeze_fs) (struct super_block *); - int (*statfs) (struct dentry *, struct kstatfs *); - int (*remount_fs) (struct super_block *, int *, char *); -+ void *(*clone_mnt_data) (void *); -+ void (*copy_mnt_data) (void *, void *); -+ void (*update_mnt_data) (void *, struct fs_context *); - void (*umount_begin) (struct super_block *); - - int (*show_options)(struct seq_file *, struct dentry *); -@@ -2234,6 +2237,7 @@ struct file_system_type { - const struct fs_parameter_description *parameters; - struct dentry *(*mount) (struct file_system_type *, int, - const char *, void *); -+ void *(*alloc_mnt_data) (void); - void (*kill_sb) (struct super_block *); - struct module *owner; - struct file_system_type * next; -diff --git a/include/linux/mount.h b/include/linux/mount.h -index bf8cc4108b8f..20541916e360 100644 ---- a/include/linux/mount.h -+++ b/include/linux/mount.h -@@ -69,6 +69,7 @@ struct vfsmount { - struct dentry *mnt_root; /* root of the mounted tree */ - struct super_block *mnt_sb; /* pointer to superblock */ - int mnt_flags; -+ void *data; - } __randomize_layout; - - struct file; /* forward dec */ diff --git a/patches/ANDROID-mnt-Fix-null-pointer-dereference.patch b/patches/ANDROID-mnt-Fix-null-pointer-dereference.patch deleted file mode 100644 index 8b1747ecfd1b939dccd1c78d4b5299bc1eebc3eb..0000000000000000000000000000000000000000 --- a/patches/ANDROID-mnt-Fix-null-pointer-dereference.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Delva -Date: Mon, 22 Jul 2019 14:29:35 -0700 -Subject: ANDROID: mnt: Fix null pointer dereference - -Fix "ANDROID: mnt: Add filesystem private data to mount points" to only -call update_mnt_data() if the filesystem provides the function. This -avoids a null pointer dereference in do_mount(). - -Reported-by: youling 257 -Signed-off-by: Alistair Delva -Signed-off-by: Daniel Rosenberg -Change-Id: I6aedaa89536ae85e6bc29093f38934c672c8fe42 ---- - fs/namespace.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/fs/namespace.c b/fs/namespace.c -index 4ec782ed6069..b7eb5f242b86 100644 ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -935,9 +935,11 @@ static struct mount *skip_mnt_tree(struct mount *p) - struct vfsmount *vfs_create_mount(struct fs_context *fc) - { - struct mount *mnt; -+ struct super_block *sb; - - if (!fc->root) - return ERR_PTR(-EINVAL); -+ sb = fc->root->d_sb; - - mnt = alloc_vfsmnt(fc->source ?: "none"); - if (!mnt) -@@ -950,7 +952,8 @@ struct vfsmount *vfs_create_mount(struct fs_context *fc) - free_vfsmnt(mnt); - return ERR_PTR(-ENOMEM); - } -- fc->root->d_sb->s_op->update_mnt_data(mnt->mnt.data, fc); -+ if (sb->s_op->update_mnt_data) -+ sb->s_op->update_mnt_data(mnt->mnt.data, fc); - } - if (fc->sb_flags & SB_KERNMOUNT) - mnt->mnt.mnt_flags = MNT_INTERNAL; -@@ -2568,7 +2571,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, - err = -EPERM; - if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) { - err = reconfigure_super(fc); -- if (!err) { -+ if (!err && sb->s_op->update_mnt_data) { - sb->s_op->update_mnt_data(mnt->mnt.data, fc); - set_mount_attributes(mnt, mnt_flags); - namespace_lock(); -@@ -2576,7 +2579,8 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, - propagate_remount(mnt); - unlock_mount_hash(); - namespace_unlock(); -- } -+ } else if (!err) -+ set_mount_attributes(mnt, mnt_flags); - } - up_write(&sb->s_umount); - } diff --git a/patches/ANDROID-net-enable-wireless-core-features-with-GKI_LEGACY_WEXT_ALLCONFIG.patch b/patches/ANDROID-net-enable-wireless-core-features-with-GKI_LEGACY_WEXT_ALLCONFIG.patch deleted file mode 100644 index 50e80fbb0099aaaf905a05eeda770f3fcf1e0b72..0000000000000000000000000000000000000000 --- a/patches/ANDROID-net-enable-wireless-core-features-with-GKI_LEGACY_WEXT_ALLCONFIG.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Salyzyn -Date: Fri, 30 Aug 2019 08:23:25 -0700 -Subject: ANDROID: net: enable wireless core features with - GKI_LEGACY_WEXT_ALLCONFIG - -In embedded environments the requirements are to be able to pick and -chose which features one requires built into the kernel. If an -embedded environment wants to supports loading modules that have been -kbuilt out of tree, there is a need to enable hidden configurations -for legacy wireless core features to provide the API surface for -them to load. - -Introduce CONFIG_GKI_LEGACY_WEXT_ALLCONFIG to select all legacy wireless -extension core features by activating in turn all the associated -hidden configuration options, without having to specifically select -any wireless module(s). - -(rejected upstream commit url https://lkml.org/lkml/2019/9/6/878) -Signed-off-by: Mark Salyzyn -Bug: 140250271 -Change-Id: Ie40e656d87ce21ae82f04ffe8dae2f0efab88a2e ---- - init/Kconfig.gki | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/init/Kconfig.gki b/init/Kconfig.gki -index 5df8c67123ef..b2f3ecefd782 100644 ---- a/init/Kconfig.gki -+++ b/init/Kconfig.gki -@@ -34,6 +34,25 @@ config GKI_HIDDEN_GPIO_CONFIGS - These are normally selected implicitely when a module - that relies on it is configured. - -+# LEGACY_WEXT_ALLCONFIG Discussed upstream, soundly rejected as a unique -+# problem for GKI to solve. It should be noted that these extensions are -+# in-effect deprecated and generally unsupported and we should pressure -+# the SOC vendors to drop any modules that require these extensions. -+config GKI_LEGACY_WEXT_ALLCONFIG -+ bool "Hidden wireless extension configs needed for GKI" -+ select WIRELESS_EXT -+ select WEXT_CORE -+ select WEXT_PROC -+ select WEXT_SPY -+ select WEXT_PRIV -+ help -+ Dummy config option used to enable all the hidden legacy wireless -+ extensions to the core wireless network functionality used by -+ add-in modules. -+ -+ If you are not building a kernel to be used for a variety of -+ out-of-kernel built wireless modules, say N here. -+ - # Atrocities needed for - # a) building GKI modules in separate tree, or - # b) building drivers that are not modularizable -@@ -47,6 +66,7 @@ config GKI_HACKS_TO_FIX - select GKI_HIDDEN_REGMAP_CONFIGS - select GKI_HIDDEN_SND_SOC_CONFIGS - select GKI_HIDDEN_GPIO_CONFIGS -+ select GKI_LEGACY_WEXT_ALLCONFIG - help - Dummy config option used to enable core functionality used by - modules that may not be selectable in this config. diff --git a/patches/ANDROID-net-ipv6-autoconf-routes-into-per-device-tables.patch b/patches/ANDROID-net-ipv6-autoconf-routes-into-per-device-tables.patch deleted file mode 100644 index c488a4ccd3413407fceb6a05a7bf37b0a85047e2..0000000000000000000000000000000000000000 --- a/patches/ANDROID-net-ipv6-autoconf-routes-into-per-device-tables.patch +++ /dev/null @@ -1,266 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lorenzo Colitti -Date: Wed, 26 Mar 2014 19:35:41 +0900 -Subject: ANDROID: net: ipv6: autoconf routes into per-device tables - -Currently, IPv6 router discovery always puts routes into -RT6_TABLE_MAIN. This causes problems for connection managers -that want to support multiple simultaneous network connections -and want control over which one is used by default (e.g., wifi -and wired). - -To work around this connection managers typically take the routes -they prefer and copy them to static routes with low metrics in -the main table. This puts the burden on the connection manager -to watch netlink to see if the routes have changed, delete the -routes when their lifetime expires, etc. - -Instead, this patch adds a per-interface sysctl to have the -kernel put autoconf routes into different tables. This allows -each interface to have its own autoconf table, and choosing the -default interface (or using different interfaces at the same -time for different types of traffic) can be done using -appropriate ip rules. - -The sysctl behaves as follows: - -- = 0: default. Put routes into RT6_TABLE_MAIN as before. -- > 0: manual. Put routes into the specified table. -- < 0: automatic. Add the absolute value of the sysctl to the - device's ifindex, and use that table. - -The automatic mode is most useful in conjunction with -net.ipv6.conf.default.accept_ra_rt_table. A connection manager -or distribution could set it to, say, -100 on boot, and -thereafter just use IP rules. - -Signed-off-by: Lorenzo Colitti -[AmitP: Refactored original changes to align with - the changes introduced by upstream commits - 830218c1add1 ("net: ipv6: Fix processing of RAs in presence of VRF"), - 8d1c802b2815 ("net/ipv6: Flip FIB entries to fib6_info"). - - Also folded following android-4.9 commit changes into this patch - be65fb01da4d ("ANDROID: net: ipv6: remove unused variable ifindex in")] -Bug: 120445791 -Change-Id: I82d16e3737d9cdfa6489e649e247894d0d60cbb1 -Signed-off-by: Amit Pundir ---- - include/linux/ipv6.h | 1 + - include/net/addrconf.h | 12 ++++++++++ - net/ipv6/addrconf.c | 33 +++++++++++++++++++++++++-- - net/ipv6/route.c | 51 ++++++++++++------------------------------ - 4 files changed, 58 insertions(+), 39 deletions(-) - -diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h -index ea7c7906591e..76cfef3d43f3 100644 ---- a/include/linux/ipv6.h -+++ b/include/linux/ipv6.h -@@ -42,6 +42,7 @@ struct ipv6_devconf { - __s32 accept_ra_rt_info_max_plen; - #endif - #endif -+ __s32 accept_ra_rt_table; - __s32 proxy_ndp; - __s32 accept_source_route; - __s32 accept_ra_from_local; -diff --git a/include/net/addrconf.h b/include/net/addrconf.h -index 3f62b347b04a..2306098a7f2d 100644 ---- a/include/net/addrconf.h -+++ b/include/net/addrconf.h -@@ -266,6 +266,18 @@ static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset) - void addrconf_prefix_rcv(struct net_device *dev, - u8 *opt, int len, bool sllao); - -+/* Determines into what table to put autoconf PIO/RIO/default routes -+ * learned on this device. -+ * -+ * - If 0, use the same table for every device. This puts routes into -+ * one of RT_TABLE_{PREFIX,INFO,DFLT} depending on the type of route -+ * (but note that these three are currently all equal to -+ * RT6_TABLE_MAIN). -+ * - If > 0, use the specified table. -+ * - If < 0, put routes into table dev->ifindex + (-rt_table). -+ */ -+u32 addrconf_rt_table(const struct net_device *dev, u32 default_table); -+ - /* - * anycast prototypes (anycast.c) - */ -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index 34ccef18b40e..b2f002624391 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -217,6 +217,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { - .accept_ra_rt_info_max_plen = 0, - #endif - #endif -+ .accept_ra_rt_table = 0, - .proxy_ndp = 0, - .accept_source_route = 0, /* we do not accept RH0 by default. */ - .disable_ipv6 = 0, -@@ -271,6 +272,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { - .accept_ra_rt_info_max_plen = 0, - #endif - #endif -+ .accept_ra_rt_table = 0, - .proxy_ndp = 0, - .accept_source_route = 0, /* we do not accept RH0 by default. */ - .disable_ipv6 = 0, -@@ -2361,6 +2363,26 @@ static void ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpad - ipv6_regen_rndid(idev); - } - -+u32 addrconf_rt_table(const struct net_device *dev, u32 default_table) -+{ -+ struct inet6_dev *idev = in6_dev_get(dev); -+ int sysctl; -+ u32 table; -+ -+ if (!idev) -+ return default_table; -+ sysctl = idev->cnf.accept_ra_rt_table; -+ if (sysctl == 0) { -+ table = default_table; -+ } else if (sysctl > 0) { -+ table = (u32) sysctl; -+ } else { -+ table = (unsigned) dev->ifindex + (-sysctl); -+ } -+ in6_dev_put(idev); -+ return table; -+} -+ - /* - * Add prefix route. - */ -@@ -2371,7 +2393,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, u32 metric, - u32 flags, gfp_t gfp_flags) - { - struct fib6_config cfg = { -- .fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_PREFIX, -+ .fc_table = l3mdev_fib_table(dev) ? : addrconf_rt_table(dev, RT6_TABLE_PREFIX), - .fc_metric = metric ? : IP6_RT_PRIO_ADDRCONF, - .fc_ifindex = dev->ifindex, - .fc_expires = expires, -@@ -2406,7 +2428,7 @@ static struct fib6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, - struct fib6_node *fn; - struct fib6_info *rt = NULL; - struct fib6_table *table; -- u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_PREFIX; -+ u32 tb_id = l3mdev_fib_table(dev) ? : addrconf_rt_table(dev, RT6_TABLE_PREFIX); - - table = fib6_get_table(dev_net(dev), tb_id); - if (!table) -@@ -6641,6 +6663,13 @@ static const struct ctl_table addrconf_sysctl[] = { - }, - #endif - #endif -+ { -+ .procname = "accept_ra_rt_table", -+ .data = &ipv6_devconf.accept_ra_rt_table, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec, -+ }, - { - .procname = "proxy_ndp", - .data = &ipv6_devconf.proxy_ndp, -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index a63ff85fe141..a9fd86522e17 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -4079,7 +4079,7 @@ static struct fib6_info *rt6_get_route_info(struct net *net, - const struct in6_addr *gwaddr, - struct net_device *dev) - { -- u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO; -+ u32 tb_id = l3mdev_fib_table(dev) ? : addrconf_rt_table(dev, RT6_TABLE_INFO); - int ifindex = dev->ifindex; - struct fib6_node *fn; - struct fib6_info *rt = NULL; -@@ -4133,7 +4133,7 @@ static struct fib6_info *rt6_add_route_info(struct net *net, - .fc_nlinfo.nl_net = net, - }; - -- cfg.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO, -+ cfg.fc_table = l3mdev_fib_table(dev) ? : addrconf_rt_table(dev, RT6_TABLE_INFO), - cfg.fc_dst = *prefix; - cfg.fc_gateway = *gwaddr; - -@@ -4151,7 +4151,7 @@ struct fib6_info *rt6_get_dflt_router(struct net *net, - const struct in6_addr *addr, - struct net_device *dev) - { -- u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_DFLT; -+ u32 tb_id = l3mdev_fib_table(dev) ? : addrconf_rt_table(dev, RT6_TABLE_DFLT); - struct fib6_info *rt; - struct fib6_table *table; - -@@ -4185,7 +4185,7 @@ struct fib6_info *rt6_add_dflt_router(struct net *net, - unsigned int pref) - { - struct fib6_config cfg = { -- .fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_DFLT, -+ .fc_table = l3mdev_fib_table(dev) ? : addrconf_rt_table(dev, RT6_TABLE_DFLT), - .fc_metric = IP6_RT_PRIO_USER, - .fc_ifindex = dev->ifindex, - .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | -@@ -4210,47 +4210,24 @@ struct fib6_info *rt6_add_dflt_router(struct net *net, - return rt6_get_dflt_router(net, gwaddr, dev); - } - --static void __rt6_purge_dflt_routers(struct net *net, -- struct fib6_table *table) -+static int rt6_addrconf_purge(struct fib6_info *rt, void *arg) - { -- struct fib6_info *rt; -- --restart: -- rcu_read_lock(); -- for_each_fib6_node_rt_rcu(&table->tb6_root) { -- struct net_device *dev = fib6_info_nh_dev(rt); -- struct inet6_dev *idev = dev ? __in6_dev_get(dev) : NULL; -+ struct net_device *dev = fib6_info_nh_dev(rt); -+ struct inet6_dev *idev = dev ? __in6_dev_get(dev) : NULL; - -- if (rt->fib6_flags & (RTF_DEFAULT | RTF_ADDRCONF) && -- (!idev || idev->cnf.accept_ra != 2) && -- fib6_info_hold_safe(rt)) { -- rcu_read_unlock(); -- ip6_del_rt(net, rt); -- goto restart; -- } -+ if (rt->fib6_flags & (RTF_DEFAULT | RTF_ADDRCONF) && -+ (!idev || idev->cnf.accept_ra != 2)) { -+ /* Delete this route. See fib6_clean_tree() */ -+ return -1; - } -- rcu_read_unlock(); - -- table->flags &= ~RT6_TABLE_HAS_DFLT_ROUTER; -+ /* Continue walking */ -+ return 0; - } - - void rt6_purge_dflt_routers(struct net *net) - { -- struct fib6_table *table; -- struct hlist_head *head; -- unsigned int h; -- -- rcu_read_lock(); -- -- for (h = 0; h < FIB6_TABLE_HASHSZ; h++) { -- head = &net->ipv6.fib_table_hash[h]; -- hlist_for_each_entry_rcu(table, head, tb6_hlist) { -- if (table->flags & RT6_TABLE_HAS_DFLT_ROUTER) -- __rt6_purge_dflt_routers(net, table); -- } -- } -- -- rcu_read_unlock(); -+ fib6_clean_all(net, rt6_addrconf_purge, NULL); - } - - static void rtmsg_to_fib6_config(struct net *net, diff --git a/patches/ANDROID-net-xfrm-make-PF_KEY-SHA256-use-RFC-compliant-truncation.patch b/patches/ANDROID-net-xfrm-make-PF_KEY-SHA256-use-RFC-compliant-truncation.patch deleted file mode 100644 index 774d1fcc6ef5fbf696bd96a33657757953f108a7..0000000000000000000000000000000000000000 --- a/patches/ANDROID-net-xfrm-make-PF_KEY-SHA256-use-RFC-compliant-truncation.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lorenzo Colitti -Date: Wed, 10 May 2017 23:54:04 +0900 -Subject: ANDROID: net: xfrm: make PF_KEY SHA256 use RFC-compliant truncation. - -When using the PF_KEY interface, SHA-256 hashes are hardcoded to -use 96-bit truncation. This is a violation of RFC4868, which -specifies 128-bit truncation, but will not be fixed upstream due -to backwards compatibility concerns and because the PF_KEY -interface is deprecated in favour of netlink XFRM (which allows -the app to specify an arbitrary truncation length). - -Change the hardcoded truncation length from 96 to 128 so that -PF_KEY apps such as racoon will work with standards-compliant VPN -servers. - -Bug: 34114242 -Bug: 120440497 -Change-Id: Ie46bff4b6358f18117d0be241171d677d31d33f7 -Signed-off-by: Lorenzo Colitti ---- - net/xfrm/xfrm_algo.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c -index 32a378e7011f..8b06ef53d7fc 100644 ---- a/net/xfrm/xfrm_algo.c -+++ b/net/xfrm/xfrm_algo.c -@@ -237,7 +237,7 @@ static struct xfrm_algo_desc aalg_list[] = { - - .uinfo = { - .auth = { -- .icv_truncbits = 96, -+ .icv_truncbits = 128, - .icv_fullbits = 256, - } - }, diff --git a/patches/ANDROID-netfilter-xt_IDLETIMER-Add-new-netlink-msg-type.patch b/patches/ANDROID-netfilter-xt_IDLETIMER-Add-new-netlink-msg-type.patch deleted file mode 100644 index 7068cc911dd7114913a45ddfb874c28fc91eb5a0..0000000000000000000000000000000000000000 --- a/patches/ANDROID-netfilter-xt_IDLETIMER-Add-new-netlink-msg-type.patch +++ /dev/null @@ -1,450 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JP Abgrall -Date: Thu, 26 Apr 2012 23:28:35 -0700 -Subject: ANDROID: netfilter: xt_IDLETIMER: Add new netlink msg type - -Send notifications when the label becomes active after an idle period. -Send netlink message notifications in addition to sysfs notifications. -Using a uevent with - subsystem=xt_idletimer - INTERFACE=... - STATE={active,inactive} - -This is backport from common android-3.0 -commit: beb914e987cbbd368988d2b94a6661cb907c4d5a -with uevent support instead of a new netlink message type. - -Bug: 120445672 -Change-Id: I31677ef00c94b5f82c8457e5bf9e5e584c23c523 -Signed-off-by: Ashish Sharma -Signed-off-by: JP Abgrall -[astrachan: Folded the following changes into this patch: - ee0b238fada5 ("netfilter: xt_IDLETIMER: time-stamp and suspend/resume handling.") - 728c058a495e ("netfilter: xt_IDLETIMER: Adds the uid field in the msg") - 5ebea489d44c ("netfilter: xt_IDLETIMER: Fix use after free condition during work") - 5ab69d7ba2c5 ("netfilter: xt_IDLETIMER: Use fullsock when querying uid")] -Signed-off-by: Alistair Strachan ---- - include/uapi/linux/netfilter/xt_IDLETIMER.h | 8 + - net/netfilter/xt_IDLETIMER.c | 251 +++++++++++++++++++- - 2 files changed, 247 insertions(+), 12 deletions(-) - -diff --git a/include/uapi/linux/netfilter/xt_IDLETIMER.h b/include/uapi/linux/netfilter/xt_IDLETIMER.h -index 3c586a19baea..c82a1c1d53ec 100644 ---- a/include/uapi/linux/netfilter/xt_IDLETIMER.h -+++ b/include/uapi/linux/netfilter/xt_IDLETIMER.h -@@ -5,6 +5,7 @@ - * Header file for Xtables timer target module. - * - * Copyright (C) 2004, 2010 Nokia Corporation -+ * - * Written by Timo Teras - * - * Converted to x_tables and forward-ported to 2.6.34 -@@ -33,12 +34,19 @@ - #include - - #define MAX_IDLETIMER_LABEL_SIZE 28 -+#define NLMSG_MAX_SIZE 64 -+ -+#define NL_EVENT_TYPE_INACTIVE 0 -+#define NL_EVENT_TYPE_ACTIVE 1 - - struct idletimer_tg_info { - __u32 timeout; - - char label[MAX_IDLETIMER_LABEL_SIZE]; - -+ /* Use netlink messages for notification in addition to sysfs */ -+ __u8 send_nl_msg; -+ - /* for kernel module internal use only */ - struct idletimer_tg *timer __attribute__((aligned(8))); - }; -diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c -index f56d3ed93e56..5f4a3229ed92 100644 ---- a/net/netfilter/xt_IDLETIMER.c -+++ b/net/netfilter/xt_IDLETIMER.c -@@ -6,6 +6,7 @@ - * After timer expires a kevent will be sent. - * - * Copyright (C) 2004, 2010 Nokia Corporation -+ * - * Written by Timo Teras - * - * Converted to x_tables and reworked for upstream inclusion -@@ -25,8 +26,17 @@ - #include - #include - #include -+#include - #include - #include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - - struct idletimer_tg { - struct list_head entry; -@@ -36,14 +46,111 @@ struct idletimer_tg { - struct kobject *kobj; - struct device_attribute attr; - -+ struct timespec64 delayed_timer_trigger; -+ struct timespec64 last_modified_timer; -+ struct timespec64 last_suspend_time; -+ struct notifier_block pm_nb; -+ -+ int timeout; - unsigned int refcnt; -+ bool work_pending; -+ bool send_nl_msg; -+ bool active; -+ uid_t uid; - }; - - static LIST_HEAD(idletimer_tg_list); - static DEFINE_MUTEX(list_mutex); -+static DEFINE_SPINLOCK(timestamp_lock); - - static struct kobject *idletimer_tg_kobj; - -+static bool check_for_delayed_trigger(struct idletimer_tg *timer, -+ struct timespec64 *ts) -+{ -+ bool state; -+ struct timespec64 temp; -+ spin_lock_bh(×tamp_lock); -+ timer->work_pending = false; -+ if ((ts->tv_sec - timer->last_modified_timer.tv_sec) > timer->timeout || -+ timer->delayed_timer_trigger.tv_sec != 0) { -+ state = false; -+ temp.tv_sec = timer->timeout; -+ temp.tv_nsec = 0; -+ if (timer->delayed_timer_trigger.tv_sec != 0) { -+ temp = timespec64_add(timer->delayed_timer_trigger, -+ temp); -+ ts->tv_sec = temp.tv_sec; -+ ts->tv_nsec = temp.tv_nsec; -+ timer->delayed_timer_trigger.tv_sec = 0; -+ timer->work_pending = true; -+ schedule_work(&timer->work); -+ } else { -+ temp = timespec64_add(timer->last_modified_timer, temp); -+ ts->tv_sec = temp.tv_sec; -+ ts->tv_nsec = temp.tv_nsec; -+ } -+ } else { -+ state = timer->active; -+ } -+ spin_unlock_bh(×tamp_lock); -+ return state; -+} -+ -+static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer) -+{ -+ char iface_msg[NLMSG_MAX_SIZE]; -+ char state_msg[NLMSG_MAX_SIZE]; -+ char timestamp_msg[NLMSG_MAX_SIZE]; -+ char uid_msg[NLMSG_MAX_SIZE]; -+ char *envp[] = { iface_msg, state_msg, timestamp_msg, uid_msg, NULL }; -+ int res; -+ struct timespec64 ts; -+ uint64_t time_ns; -+ bool state; -+ -+ res = snprintf(iface_msg, NLMSG_MAX_SIZE, "INTERFACE=%s", -+ iface); -+ if (NLMSG_MAX_SIZE <= res) { -+ pr_err("message too long (%d)", res); -+ return; -+ } -+ -+ ts = ktime_to_timespec64(ktime_get_boottime()); -+ state = check_for_delayed_trigger(timer, &ts); -+ res = snprintf(state_msg, NLMSG_MAX_SIZE, "STATE=%s", -+ state ? "active" : "inactive"); -+ -+ if (NLMSG_MAX_SIZE <= res) { -+ pr_err("message too long (%d)", res); -+ return; -+ } -+ -+ if (state) { -+ res = snprintf(uid_msg, NLMSG_MAX_SIZE, "UID=%u", timer->uid); -+ if (NLMSG_MAX_SIZE <= res) -+ pr_err("message too long (%d)", res); -+ } else { -+ res = snprintf(uid_msg, NLMSG_MAX_SIZE, "UID="); -+ if (NLMSG_MAX_SIZE <= res) -+ pr_err("message too long (%d)", res); -+ } -+ -+ time_ns = timespec64_to_ns(&ts); -+ res = snprintf(timestamp_msg, NLMSG_MAX_SIZE, "TIME_NS=%llu", time_ns); -+ if (NLMSG_MAX_SIZE <= res) { -+ timestamp_msg[0] = '\0'; -+ pr_err("message too long (%d)", res); -+ } -+ -+ pr_debug("putting nlmsg: <%s> <%s> <%s> <%s>\n", iface_msg, state_msg, -+ timestamp_msg, uid_msg); -+ kobject_uevent_env(idletimer_tg_kobj, KOBJ_CHANGE, envp); -+ return; -+ -+ -+} -+ - static - struct idletimer_tg *__idletimer_tg_find_by_label(const char *label) - { -@@ -62,6 +169,7 @@ static ssize_t idletimer_tg_show(struct device *dev, - { - struct idletimer_tg *timer; - unsigned long expires = 0; -+ unsigned long now = jiffies; - - mutex_lock(&list_mutex); - -@@ -71,11 +179,15 @@ static ssize_t idletimer_tg_show(struct device *dev, - - mutex_unlock(&list_mutex); - -- if (time_after(expires, jiffies)) -+ if (time_after(expires, now)) - return sprintf(buf, "%u\n", -- jiffies_to_msecs(expires - jiffies) / 1000); -+ jiffies_to_msecs(expires - now) / 1000); - -- return sprintf(buf, "0\n"); -+ if (timer->send_nl_msg) -+ return sprintf(buf, "0 %d\n", -+ jiffies_to_msecs(now - expires) / 1000); -+ else -+ return sprintf(buf, "0\n"); - } - - static void idletimer_tg_work(struct work_struct *work) -@@ -84,6 +196,9 @@ static void idletimer_tg_work(struct work_struct *work) - work); - - sysfs_notify(idletimer_tg_kobj, NULL, timer->attr.attr.name); -+ -+ if (timer->send_nl_msg) -+ notify_netlink_uevent(timer->attr.attr.name, timer); - } - - static void idletimer_tg_expired(struct timer_list *t) -@@ -91,8 +206,56 @@ static void idletimer_tg_expired(struct timer_list *t) - struct idletimer_tg *timer = from_timer(timer, t, timer); - - pr_debug("timer %s expired\n", timer->attr.attr.name); -- -+ spin_lock_bh(×tamp_lock); -+ timer->active = false; -+ timer->work_pending = true; - schedule_work(&timer->work); -+ spin_unlock_bh(×tamp_lock); -+} -+ -+static int idletimer_resume(struct notifier_block *notifier, -+ unsigned long pm_event, void *unused) -+{ -+ struct timespec64 ts; -+ unsigned long time_diff, now = jiffies; -+ struct idletimer_tg *timer = container_of(notifier, -+ struct idletimer_tg, pm_nb); -+ if (!timer) -+ return NOTIFY_DONE; -+ switch (pm_event) { -+ case PM_SUSPEND_PREPARE: -+ timer->last_suspend_time = -+ ktime_to_timespec64(ktime_get_boottime()); -+ break; -+ case PM_POST_SUSPEND: -+ spin_lock_bh(×tamp_lock); -+ if (!timer->active) { -+ spin_unlock_bh(×tamp_lock); -+ break; -+ } -+ /* since jiffies are not updated when suspended now represents -+ * the time it would have suspended */ -+ if (time_after(timer->timer.expires, now)) { -+ ts = ktime_to_timespec64(ktime_get_boottime()); -+ ts = timespec64_sub(ts, timer->last_suspend_time); -+ time_diff = timespec64_to_jiffies(&ts); -+ if (timer->timer.expires > (time_diff + now)) { -+ mod_timer_pending(&timer->timer, -+ (timer->timer.expires - time_diff)); -+ } else { -+ del_timer(&timer->timer); -+ timer->timer.expires = 0; -+ timer->active = false; -+ timer->work_pending = true; -+ schedule_work(&timer->work); -+ } -+ } -+ spin_unlock_bh(×tamp_lock); -+ break; -+ default: -+ break; -+ } -+ return NOTIFY_DONE; - } - - static int idletimer_check_sysfs_name(const char *name, unsigned int size) -@@ -144,6 +307,22 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) - - timer_setup(&info->timer->timer, idletimer_tg_expired, 0); - info->timer->refcnt = 1; -+ info->timer->send_nl_msg = (info->send_nl_msg == 0) ? false : true; -+ info->timer->active = true; -+ info->timer->timeout = info->timeout; -+ -+ info->timer->delayed_timer_trigger.tv_sec = 0; -+ info->timer->delayed_timer_trigger.tv_nsec = 0; -+ info->timer->work_pending = false; -+ info->timer->uid = 0; -+ info->timer->last_modified_timer = -+ ktime_to_timespec64(ktime_get_boottime()); -+ -+ info->timer->pm_nb.notifier_call = idletimer_resume; -+ ret = register_pm_notifier(&info->timer->pm_nb); -+ if (ret) -+ printk(KERN_WARNING "[%s] Failed to register pm notifier %d\n", -+ __func__, ret); - - INIT_WORK(&info->timer->work, idletimer_tg_work); - -@@ -160,6 +339,42 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) - return ret; - } - -+static void reset_timer(const struct idletimer_tg_info *info, -+ struct sk_buff *skb) -+{ -+ unsigned long now = jiffies; -+ struct idletimer_tg *timer = info->timer; -+ bool timer_prev; -+ -+ spin_lock_bh(×tamp_lock); -+ timer_prev = timer->active; -+ timer->active = true; -+ /* timer_prev is used to guard overflow problem in time_before*/ -+ if (!timer_prev || time_before(timer->timer.expires, now)) { -+ pr_debug("Starting Checkentry timer (Expired, Jiffies): %lu, %lu\n", -+ timer->timer.expires, now); -+ -+ /* Stores the uid resposible for waking up the radio */ -+ if (skb && (skb->sk)) { -+ timer->uid = from_kuid_munged(current_user_ns(), -+ sock_i_uid(skb_to_full_sk(skb))); -+ } -+ -+ /* checks if there is a pending inactive notification*/ -+ if (timer->work_pending) -+ timer->delayed_timer_trigger = timer->last_modified_timer; -+ else { -+ timer->work_pending = true; -+ schedule_work(&timer->work); -+ } -+ } -+ -+ timer->last_modified_timer = ktime_to_timespec64(ktime_get_boottime()); -+ mod_timer(&timer->timer, -+ msecs_to_jiffies(info->timeout * 1000) + now); -+ spin_unlock_bh(×tamp_lock); -+} -+ - /* - * The actual xt_tables plugin. - */ -@@ -167,13 +382,23 @@ static unsigned int idletimer_tg_target(struct sk_buff *skb, - const struct xt_action_param *par) - { - const struct idletimer_tg_info *info = par->targinfo; -+ unsigned long now = jiffies; - - pr_debug("resetting timer %s, timeout period %u\n", - info->label, info->timeout); - -- mod_timer(&info->timer->timer, -- msecs_to_jiffies(info->timeout * 1000) + jiffies); -+ BUG_ON(!info->timer); -+ -+ info->timer->active = true; -+ -+ if (time_before(info->timer->timer.expires, now)) { -+ schedule_work(&info->timer->work); -+ pr_debug("Starting timer %s (Expired, Jiffies): %lu, %lu\n", -+ info->label, info->timer->timer.expires, now); -+ } - -+ /* TODO: Avoid modifying timers on each packet */ -+ reset_timer(info, skb); - return XT_CONTINUE; - } - -@@ -182,7 +407,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par) - struct idletimer_tg_info *info = par->targinfo; - int ret; - -- pr_debug("checkentry targinfo%s\n", info->label); -+ pr_debug("checkentry targinfo %s\n", info->label); - - if (info->timeout == 0) { - pr_debug("timeout value is zero\n"); -@@ -204,9 +429,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par) - info->timer = __idletimer_tg_find_by_label(info->label); - if (info->timer) { - info->timer->refcnt++; -- mod_timer(&info->timer->timer, -- msecs_to_jiffies(info->timeout * 1000) + jiffies); -- -+ reset_timer(info, NULL); - pr_debug("increased refcnt of timer %s to %u\n", - info->label, info->timer->refcnt); - } else { -@@ -219,6 +442,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par) - } - - mutex_unlock(&list_mutex); -+ - return 0; - } - -@@ -235,13 +459,14 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par) - - list_del(&info->timer->entry); - del_timer_sync(&info->timer->timer); -- cancel_work_sync(&info->timer->work); - sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr); -+ unregister_pm_notifier(&info->timer->pm_nb); -+ cancel_work_sync(&info->timer->work); - kfree(info->timer->attr.attr.name); - kfree(info->timer); - } else { - pr_debug("decreased refcnt of timer %s to %u\n", -- info->label, info->timer->refcnt); -+ info->label, info->timer->refcnt); - } - - mutex_unlock(&list_mutex); -@@ -249,6 +474,7 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par) - - static struct xt_target idletimer_tg __read_mostly = { - .name = "IDLETIMER", -+ .revision = 1, - .family = NFPROTO_UNSPEC, - .target = idletimer_tg_target, - .targetsize = sizeof(struct idletimer_tg_info), -@@ -315,3 +541,4 @@ MODULE_DESCRIPTION("Xtables: idle time monitor"); - MODULE_LICENSE("GPL v2"); - MODULE_ALIAS("ipt_IDLETIMER"); - MODULE_ALIAS("ip6t_IDLETIMER"); -+MODULE_ALIAS("arpt_IDLETIMER"); diff --git a/patches/ANDROID-netfilter-xt_quota2-adding-the-original-quota2-from-xtables-addons.patch b/patches/ANDROID-netfilter-xt_quota2-adding-the-original-quota2-from-xtables-addons.patch deleted file mode 100644 index 18ec993a490ef968c2a37a99d3075b1ec44a2e6d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-netfilter-xt_quota2-adding-the-original-quota2-from-xtables-addons.patch +++ /dev/null @@ -1,515 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: JP Abgrall -Date: Tue, 21 Jun 2011 11:14:49 -0700 -Subject: ANDROID: netfilter: xt_quota2: adding the original quota2 from - xtables-addons - -The original xt_quota in the kernel is plain broken: - - counts quota at a per CPU level - (was written back when ubiquitous SMP was just a dream) - - provides no way to count across IPV4/IPV6. - -This patch is the original unaltered code from: - http://sourceforge.net/projects/xtables-addons - - at commit e84391ce665cef046967f796dd91026851d6bbf3 - -Bug: 120445421 -Change-Id: I19d49858840effee9ecf6cff03c23b45a97efdeb -Signed-off-by: JP Abgrall -[astrachan: Folded 4d33aa305871 ("netfilter: xt_quota2: fixup the quota2, - and enable.") into this patch] -Signed-off-by: Alistair Strachan ---- - include/linux/netfilter/xt_quota2.h | 25 ++ - net/netfilter/Kconfig | 23 ++ - net/netfilter/Makefile | 1 + - net/netfilter/xt_quota2.c | 401 ++++++++++++++++++++++++++++ - 4 files changed, 450 insertions(+) - create mode 100644 include/linux/netfilter/xt_quota2.h - create mode 100644 net/netfilter/xt_quota2.c - -diff --git a/include/linux/netfilter/xt_quota2.h b/include/linux/netfilter/xt_quota2.h -new file mode 100644 -index 000000000000..eadc6903314e ---- /dev/null -+++ b/include/linux/netfilter/xt_quota2.h -@@ -0,0 +1,25 @@ -+#ifndef _XT_QUOTA_H -+#define _XT_QUOTA_H -+ -+enum xt_quota_flags { -+ XT_QUOTA_INVERT = 1 << 0, -+ XT_QUOTA_GROW = 1 << 1, -+ XT_QUOTA_PACKET = 1 << 2, -+ XT_QUOTA_NO_CHANGE = 1 << 3, -+ XT_QUOTA_MASK = 0x0F, -+}; -+ -+struct xt_quota_counter; -+ -+struct xt_quota_mtinfo2 { -+ char name[15]; -+ u_int8_t flags; -+ -+ /* Comparison-invariant */ -+ aligned_u64 quota; -+ -+ /* Used internally by the kernel */ -+ struct xt_quota_counter *master __attribute__((aligned(8))); -+}; -+ -+#endif /* _XT_QUOTA_H */ -diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig -index 91efae88e8c2..ea957f78a5a9 100644 ---- a/net/netfilter/Kconfig -+++ b/net/netfilter/Kconfig -@@ -1484,6 +1484,29 @@ config NETFILTER_XT_MATCH_QUOTA - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -+config NETFILTER_XT_MATCH_QUOTA2 -+ tristate '"quota2" match support' -+ depends on NETFILTER_ADVANCED -+ help -+ This option adds a `quota2' match, which allows to match on a -+ byte counter correctly and not per CPU. -+ It allows naming the quotas. -+ This is based on http://xtables-addons.git.sourceforge.net -+ -+ If you want to compile it as a module, say M here and read -+ . If unsure, say `N'. -+ -+config NETFILTER_XT_MATCH_QUOTA2_LOG -+ bool '"quota2" Netfilter LOG support' -+ depends on NETFILTER_XT_MATCH_QUOTA2 -+ default n -+ help -+ This option allows `quota2' to log ONCE when a quota limit -+ is passed. It logs via NETLINK using the NETLINK_NFLOG family. -+ It logs similarly to how ipt_ULOG would without data. -+ -+ If unsure, say `N'. -+ - config NETFILTER_XT_MATCH_RATEEST - tristate '"rateest" match support' - depends on NETFILTER_ADVANCED -diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile -index 4fc075b612fe..f3e1af382948 100644 ---- a/net/netfilter/Makefile -+++ b/net/netfilter/Makefile -@@ -192,6 +192,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o - obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o - obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o - obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o -+obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA2) += xt_quota2.o - obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o - obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o - obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) += xt_recent.o -diff --git a/net/netfilter/xt_quota2.c b/net/netfilter/xt_quota2.c -new file mode 100644 -index 000000000000..24b774263aa6 ---- /dev/null -+++ b/net/netfilter/xt_quota2.c -@@ -0,0 +1,401 @@ -+/* -+ * xt_quota2 - enhanced xt_quota that can count upwards and in packets -+ * as a minimal accounting match. -+ * by Jan Engelhardt , 2008 -+ * -+ * Originally based on xt_quota.c: -+ * netfilter module to enforce network quotas -+ * Sam Johnston -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License; either -+ * version 2 of the License, as published by the Free Software Foundation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG -+/* For compatibility, these definitions are copied from the -+ * deprecated header file */ -+#define ULOG_MAC_LEN 80 -+#define ULOG_PREFIX_LEN 32 -+ -+/* Format of the ULOG packets passed through netlink */ -+typedef struct ulog_packet_msg { -+ unsigned long mark; -+ long timestamp_sec; -+ long timestamp_usec; -+ unsigned int hook; -+ char indev_name[IFNAMSIZ]; -+ char outdev_name[IFNAMSIZ]; -+ size_t data_len; -+ char prefix[ULOG_PREFIX_LEN]; -+ unsigned char mac_len; -+ unsigned char mac[ULOG_MAC_LEN]; -+ unsigned char payload[0]; -+} ulog_packet_msg_t; -+#endif -+ -+/** -+ * @lock: lock to protect quota writers from each other -+ */ -+struct xt_quota_counter { -+ u_int64_t quota; -+ spinlock_t lock; -+ struct list_head list; -+ atomic_t ref; -+ char name[sizeof(((struct xt_quota_mtinfo2 *)NULL)->name)]; -+ struct proc_dir_entry *procfs_entry; -+}; -+ -+#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG -+/* Harald's favorite number +1 :D From ipt_ULOG.C */ -+static int qlog_nl_event = 112; -+module_param_named(event_num, qlog_nl_event, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(event_num, -+ "Event number for NETLINK_NFLOG message. 0 disables log." -+ "111 is what ipt_ULOG uses."); -+static struct sock *nflognl; -+#endif -+ -+static LIST_HEAD(counter_list); -+static DEFINE_SPINLOCK(counter_list_lock); -+ -+static struct proc_dir_entry *proc_xt_quota; -+static unsigned int quota_list_perms = S_IRUGO | S_IWUSR; -+static kuid_t quota_list_uid = KUIDT_INIT(0); -+static kgid_t quota_list_gid = KGIDT_INIT(0); -+module_param_named(perms, quota_list_perms, uint, S_IRUGO | S_IWUSR); -+ -+#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG -+static void quota2_log(unsigned int hooknum, -+ const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const char *prefix) -+{ -+ ulog_packet_msg_t *pm; -+ struct sk_buff *log_skb; -+ size_t size; -+ struct nlmsghdr *nlh; -+ -+ if (!qlog_nl_event) -+ return; -+ -+ size = NLMSG_SPACE(sizeof(*pm)); -+ size = max(size, (size_t)NLMSG_GOODSIZE); -+ log_skb = alloc_skb(size, GFP_ATOMIC); -+ if (!log_skb) { -+ pr_err("xt_quota2: cannot alloc skb for logging\n"); -+ return; -+ } -+ -+ nlh = nlmsg_put(log_skb, /*pid*/0, /*seq*/0, qlog_nl_event, -+ sizeof(*pm), 0); -+ if (!nlh) { -+ pr_err("xt_quota2: nlmsg_put failed\n"); -+ kfree_skb(log_skb); -+ return; -+ } -+ pm = nlmsg_data(nlh); -+ if (skb->tstamp == 0) -+ __net_timestamp((struct sk_buff *)skb); -+ pm->data_len = 0; -+ pm->hook = hooknum; -+ if (prefix != NULL) -+ strlcpy(pm->prefix, prefix, sizeof(pm->prefix)); -+ else -+ *(pm->prefix) = '\0'; -+ if (in) -+ strlcpy(pm->indev_name, in->name, sizeof(pm->indev_name)); -+ else -+ pm->indev_name[0] = '\0'; -+ -+ if (out) -+ strlcpy(pm->outdev_name, out->name, sizeof(pm->outdev_name)); -+ else -+ pm->outdev_name[0] = '\0'; -+ -+ NETLINK_CB(log_skb).dst_group = 1; -+ pr_debug("throwing 1 packets to netlink group 1\n"); -+ netlink_broadcast(nflognl, log_skb, 0, 1, GFP_ATOMIC); -+} -+#else -+static void quota2_log(unsigned int hooknum, -+ const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const char *prefix) -+{ -+} -+#endif /* if+else CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG */ -+ -+static ssize_t quota_proc_read(struct file *file, char __user *buf, -+ size_t size, loff_t *ppos) -+{ -+ struct xt_quota_counter *e = PDE_DATA(file_inode(file)); -+ char tmp[24]; -+ size_t tmp_size; -+ -+ spin_lock_bh(&e->lock); -+ tmp_size = scnprintf(tmp, sizeof(tmp), "%llu\n", e->quota); -+ spin_unlock_bh(&e->lock); -+ return simple_read_from_buffer(buf, size, ppos, tmp, tmp_size); -+} -+ -+static ssize_t quota_proc_write(struct file *file, const char __user *input, -+ size_t size, loff_t *ppos) -+{ -+ struct xt_quota_counter *e = PDE_DATA(file_inode(file)); -+ char buf[sizeof("18446744073709551616")]; -+ -+ if (size > sizeof(buf)) -+ size = sizeof(buf); -+ if (copy_from_user(buf, input, size) != 0) -+ return -EFAULT; -+ buf[sizeof(buf)-1] = '\0'; -+ -+ spin_lock_bh(&e->lock); -+ e->quota = simple_strtoull(buf, NULL, 0); -+ spin_unlock_bh(&e->lock); -+ return size; -+} -+ -+static const struct file_operations q2_counter_fops = { -+ .read = quota_proc_read, -+ .write = quota_proc_write, -+ .llseek = default_llseek, -+}; -+ -+static struct xt_quota_counter * -+q2_new_counter(const struct xt_quota_mtinfo2 *q, bool anon) -+{ -+ struct xt_quota_counter *e; -+ unsigned int size; -+ -+ /* Do not need all the procfs things for anonymous counters. */ -+ size = anon ? offsetof(typeof(*e), list) : sizeof(*e); -+ e = kmalloc(size, GFP_KERNEL); -+ if (e == NULL) -+ return NULL; -+ -+ e->quota = q->quota; -+ spin_lock_init(&e->lock); -+ if (!anon) { -+ INIT_LIST_HEAD(&e->list); -+ atomic_set(&e->ref, 1); -+ strlcpy(e->name, q->name, sizeof(e->name)); -+ } -+ return e; -+} -+ -+/** -+ * q2_get_counter - get ref to counter or create new -+ * @name: name of counter -+ */ -+static struct xt_quota_counter * -+q2_get_counter(const struct xt_quota_mtinfo2 *q) -+{ -+ struct proc_dir_entry *p; -+ struct xt_quota_counter *e = NULL; -+ struct xt_quota_counter *new_e; -+ -+ if (*q->name == '\0') -+ return q2_new_counter(q, true); -+ -+ /* No need to hold a lock while getting a new counter */ -+ new_e = q2_new_counter(q, false); -+ if (new_e == NULL) -+ goto out; -+ -+ spin_lock_bh(&counter_list_lock); -+ list_for_each_entry(e, &counter_list, list) -+ if (strcmp(e->name, q->name) == 0) { -+ atomic_inc(&e->ref); -+ spin_unlock_bh(&counter_list_lock); -+ kfree(new_e); -+ pr_debug("xt_quota2: old counter name=%s", e->name); -+ return e; -+ } -+ e = new_e; -+ pr_debug("xt_quota2: new_counter name=%s", e->name); -+ list_add_tail(&e->list, &counter_list); -+ /* The entry having a refcount of 1 is not directly destructible. -+ * This func has not yet returned the new entry, thus iptables -+ * has not references for destroying this entry. -+ * For another rule to try to destroy it, it would 1st need for this -+ * func* to be re-invoked, acquire a new ref for the same named quota. -+ * Nobody will access the e->procfs_entry either. -+ * So release the lock. */ -+ spin_unlock_bh(&counter_list_lock); -+ -+ /* create_proc_entry() is not spin_lock happy */ -+ p = e->procfs_entry = proc_create_data(e->name, quota_list_perms, -+ proc_xt_quota, &q2_counter_fops, e); -+ -+ if (IS_ERR_OR_NULL(p)) { -+ spin_lock_bh(&counter_list_lock); -+ list_del(&e->list); -+ spin_unlock_bh(&counter_list_lock); -+ goto out; -+ } -+ proc_set_user(p, quota_list_uid, quota_list_gid); -+ return e; -+ -+ out: -+ kfree(e); -+ return NULL; -+} -+ -+static int quota_mt2_check(const struct xt_mtchk_param *par) -+{ -+ struct xt_quota_mtinfo2 *q = par->matchinfo; -+ -+ pr_debug("xt_quota2: check() flags=0x%04x", q->flags); -+ -+ if (q->flags & ~XT_QUOTA_MASK) -+ return -EINVAL; -+ -+ q->name[sizeof(q->name)-1] = '\0'; -+ if (*q->name == '.' || strchr(q->name, '/') != NULL) { -+ printk(KERN_ERR "xt_quota.3: illegal name\n"); -+ return -EINVAL; -+ } -+ -+ q->master = q2_get_counter(q); -+ if (q->master == NULL) { -+ printk(KERN_ERR "xt_quota.3: memory alloc failure\n"); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void quota_mt2_destroy(const struct xt_mtdtor_param *par) -+{ -+ struct xt_quota_mtinfo2 *q = par->matchinfo; -+ struct xt_quota_counter *e = q->master; -+ -+ if (*q->name == '\0') { -+ kfree(e); -+ return; -+ } -+ -+ spin_lock_bh(&counter_list_lock); -+ if (!atomic_dec_and_test(&e->ref)) { -+ spin_unlock_bh(&counter_list_lock); -+ return; -+ } -+ -+ list_del(&e->list); -+ remove_proc_entry(e->name, proc_xt_quota); -+ spin_unlock_bh(&counter_list_lock); -+ kfree(e); -+} -+ -+static bool -+quota_mt2(const struct sk_buff *skb, struct xt_action_param *par) -+{ -+ struct xt_quota_mtinfo2 *q = (void *)par->matchinfo; -+ struct xt_quota_counter *e = q->master; -+ bool ret = q->flags & XT_QUOTA_INVERT; -+ -+ spin_lock_bh(&e->lock); -+ if (q->flags & XT_QUOTA_GROW) { -+ /* -+ * While no_change is pointless in "grow" mode, we will -+ * implement it here simply to have a consistent behavior. -+ */ -+ if (!(q->flags & XT_QUOTA_NO_CHANGE)) { -+ e->quota += (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; -+ } -+ ret = true; -+ } else { -+ if (e->quota >= skb->len) { -+ if (!(q->flags & XT_QUOTA_NO_CHANGE)) -+ e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; -+ ret = !ret; -+ } else { -+ /* We are transitioning, log that fact. */ -+ if (e->quota) { -+ quota2_log(xt_hooknum(par), -+ skb, -+ xt_in(par), -+ xt_out(par), -+ q->name); -+ } -+ /* we do not allow even small packets from now on */ -+ e->quota = 0; -+ } -+ } -+ spin_unlock_bh(&e->lock); -+ return ret; -+} -+ -+static struct xt_match quota_mt2_reg[] __read_mostly = { -+ { -+ .name = "quota2", -+ .revision = 3, -+ .family = NFPROTO_IPV4, -+ .checkentry = quota_mt2_check, -+ .match = quota_mt2, -+ .destroy = quota_mt2_destroy, -+ .matchsize = sizeof(struct xt_quota_mtinfo2), -+ .me = THIS_MODULE, -+ }, -+ { -+ .name = "quota2", -+ .revision = 3, -+ .family = NFPROTO_IPV6, -+ .checkentry = quota_mt2_check, -+ .match = quota_mt2, -+ .destroy = quota_mt2_destroy, -+ .matchsize = sizeof(struct xt_quota_mtinfo2), -+ .me = THIS_MODULE, -+ }, -+}; -+ -+static int __init quota_mt2_init(void) -+{ -+ int ret; -+ pr_debug("xt_quota2: init()"); -+ -+#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG -+ nflognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, NULL); -+ if (!nflognl) -+ return -ENOMEM; -+#endif -+ -+ proc_xt_quota = proc_mkdir("xt_quota", init_net.proc_net); -+ if (proc_xt_quota == NULL) -+ return -EACCES; -+ -+ ret = xt_register_matches(quota_mt2_reg, ARRAY_SIZE(quota_mt2_reg)); -+ if (ret < 0) -+ remove_proc_entry("xt_quota", init_net.proc_net); -+ pr_debug("xt_quota2: init() %d", ret); -+ return ret; -+} -+ -+static void __exit quota_mt2_exit(void) -+{ -+ xt_unregister_matches(quota_mt2_reg, ARRAY_SIZE(quota_mt2_reg)); -+ remove_proc_entry("xt_quota", init_net.proc_net); -+} -+ -+module_init(quota_mt2_init); -+module_exit(quota_mt2_exit); -+MODULE_DESCRIPTION("Xtables: countdown quota match; up counter"); -+MODULE_AUTHOR("Sam Johnston "); -+MODULE_AUTHOR("Jan Engelhardt "); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("ipt_quota2"); -+MODULE_ALIAS("ip6t_quota2"); diff --git a/patches/ANDROID-of-Support-CONFIG_CMDLINE_EXTEND-config-option.patch b/patches/ANDROID-of-Support-CONFIG_CMDLINE_EXTEND-config-option.patch deleted file mode 100644 index 4973521f716882b2017fc0e238fa84b518ac327a..0000000000000000000000000000000000000000 --- a/patches/ANDROID-of-Support-CONFIG_CMDLINE_EXTEND-config-option.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Doug Anderson -Date: Thu, 2 Feb 2012 22:58:28 -0800 -Subject: ANDROID: of: Support CONFIG_CMDLINE_EXTEND config option - -The old logic assumes CMDLINE_FROM_BOOTLOADER vs. CMDLINE_FORCE and -ignores CMDLINE_EXTEND. Here's the old logic: - -- CONFIG_CMDLINE_FORCE=true - CONFIG_CMDLINE -- dt bootargs=non-empty: - dt bootargs -- dt bootargs=empty, @data is non-empty string - @data is left unchanged -- dt bootargs=empty, @data is empty string - CONFIG_CMDLINE (or "" if that's not defined) - -The new logic is now documented in of_fdt.h and is copied here for -reference: - -- CONFIG_CMDLINE_FORCE=true - CONFIG_CMDLINE -- CONFIG_CMDLINE_EXTEND=true, @data is non-empty string - @data + dt bootargs (even if dt bootargs are empty) -- CONFIG_CMDLINE_EXTEND=true, @data is empty string - CONFIG_CMDLINE + dt bootargs (even if dt bootargs are empty) -- CMDLINE_FROM_BOOTLOADER=true, dt bootargs=non-empty: - dt bootargs -- CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is non-empty string - @data is left unchanged -- CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is empty string - CONFIG_CMDLINE (or "" if that's not defined) - -Signed-off-by: Doug Anderson -CC: devicetree-discuss@lists.ozlabs.org -CC: Grant Likely -CC: Benjamin Herrenschmidt -CC: Rob Herring -Bug: 120440972 -Change-Id: I40ace250847f813358125dfcaa8998fd32cf7ea3 -Signed-off-by: Colin Cross -[AmitP: Folded following android-4.9 commit changes into this patch - e820270abb5d ("ANDROID: of: fix CONFIG_CMDLINE_EXTEND") - 9a4a74055444 ("ANDROID: of: Fix build warnings")] -Signed-off-by: Amit Pundir ---- - drivers/of/fdt.c | 74 ++++++++++++++++++++++++++++-------------- - include/linux/of_fdt.h | 21 ++++++++++++ - 2 files changed, 70 insertions(+), 25 deletions(-) - -diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c -index 223d617ecfe1..650c028de779 100644 ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -1040,43 +1040,67 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, - return 0; - } - -+/* -+ * Convert configs to something easy to use in C code -+ */ -+#if defined(CONFIG_CMDLINE_FORCE) -+static const int overwrite_incoming_cmdline = 1; -+static const int read_dt_cmdline; -+static const int concat_cmdline; -+#elif defined(CONFIG_CMDLINE_EXTEND) -+static const int overwrite_incoming_cmdline; -+static const int read_dt_cmdline = 1; -+static const int concat_cmdline = 1; -+#else /* CMDLINE_FROM_BOOTLOADER */ -+static const int overwrite_incoming_cmdline; -+static const int read_dt_cmdline = 1; -+static const int concat_cmdline; -+#endif -+ -+#ifdef CONFIG_CMDLINE -+static const char *config_cmdline = CONFIG_CMDLINE; -+#else -+static const char *config_cmdline = ""; -+#endif -+ - int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, - int depth, void *data) - { -- int l; -- const char *p; -+ int l = 0; -+ const char *p = NULL; - const void *rng_seed; -+ char *cmdline = data; - - pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); - -- if (depth != 1 || !data || -+ if (depth != 1 || !cmdline || - (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) - return 0; - - early_init_dt_check_for_initrd(node); - -- /* Retrieve command line */ -- p = of_get_flat_dt_prop(node, "bootargs", &l); -- if (p != NULL && l > 0) -- strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); -- -- /* -- * CONFIG_CMDLINE is meant to be a default in case nothing else -- * managed to set the command line, unless CONFIG_CMDLINE_FORCE -- * is set in which case we override whatever was found earlier. -- */ --#ifdef CONFIG_CMDLINE --#if defined(CONFIG_CMDLINE_EXTEND) -- strlcat(data, " ", COMMAND_LINE_SIZE); -- strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); --#elif defined(CONFIG_CMDLINE_FORCE) -- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); --#else -- /* No arguments from boot loader, use kernel's cmdl*/ -- if (!((char *)data)[0]) -- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); --#endif --#endif /* CONFIG_CMDLINE */ -+ /* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */ -+ if (overwrite_incoming_cmdline || !cmdline[0]) -+ strlcpy(cmdline, config_cmdline, COMMAND_LINE_SIZE); -+ -+ /* Retrieve command line unless forcing */ -+ if (read_dt_cmdline) -+ p = of_get_flat_dt_prop(node, "bootargs", &l); -+ -+ if (p != NULL && l > 0) { -+ if (concat_cmdline) { -+ int cmdline_len; -+ int copy_len; -+ strlcat(cmdline, " ", COMMAND_LINE_SIZE); -+ cmdline_len = strlen(cmdline); -+ copy_len = COMMAND_LINE_SIZE - cmdline_len - 1; -+ copy_len = min((int)l, copy_len); -+ strncpy(cmdline + cmdline_len, p, copy_len); -+ cmdline[cmdline_len + copy_len] = '\0'; -+ } else { -+ strlcpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); -+ } -+ } - - pr_debug("Command line is: %s\n", (char*)data); - -diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h -index acf820e88952..9bbd5c06cb39 100644 ---- a/include/linux/of_fdt.h -+++ b/include/linux/of_fdt.h -@@ -58,6 +58,27 @@ extern int of_flat_dt_is_compatible(unsigned long node, const char *name); - extern unsigned long of_get_flat_dt_root(void); - extern uint32_t of_get_flat_dt_phandle(unsigned long node); - -+/* -+ * early_init_dt_scan_chosen - scan the device tree for ramdisk and bootargs -+ * -+ * The boot arguments will be placed into the memory pointed to by @data. -+ * That memory should be COMMAND_LINE_SIZE big and initialized to be a valid -+ * (possibly empty) string. Logic for what will be in @data after this -+ * function finishes: -+ * -+ * - CONFIG_CMDLINE_FORCE=true -+ * CONFIG_CMDLINE -+ * - CONFIG_CMDLINE_EXTEND=true, @data is non-empty string -+ * @data + dt bootargs (even if dt bootargs are empty) -+ * - CONFIG_CMDLINE_EXTEND=true, @data is empty string -+ * CONFIG_CMDLINE + dt bootargs (even if dt bootargs are empty) -+ * - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=non-empty: -+ * dt bootargs -+ * - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is non-empty string -+ * @data is left unchanged -+ * - CMDLINE_FROM_BOOTLOADER=true, dt bootargs=empty, @data is empty string -+ * CONFIG_CMDLINE (or "" if that's not defined) -+ */ - extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, - int depth, void *data); - extern int early_init_dt_scan_memory(unsigned long node, const char *uname, diff --git a/patches/ANDROID-power-wakeup_reason-add-an-API-to-log-wakeup-reasons.patch b/patches/ANDROID-power-wakeup_reason-add-an-API-to-log-wakeup-reasons.patch deleted file mode 100644 index acfe8cb9fe5055b03f5cceb33d00a3d2b1177f03..0000000000000000000000000000000000000000 --- a/patches/ANDROID-power-wakeup_reason-add-an-API-to-log-wakeup-reasons.patch +++ /dev/null @@ -1,584 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ruchi Kandoi -Date: Wed, 19 Feb 2014 15:30:47 -0800 -Subject: ANDROID: power: wakeup_reason: add an API to log wakeup reasons - -Add API log_wakeup_reason() and expose it to userspace via sysfs path -/sys/kernel/wakeup_reasons/last_resume_reason - -Bug: 120445600 -Signed-off-by: Ruchi Kandoi -[AmitP: Folded following android-4.9 commit changes into this patch - 1135122a192a ("ANDROID: POWER: fix compile warnings in log_wakeup_reason") - b4e6247778b0 ("ANDROID: Power: Changes the permission to read only for sysfs file /sys/kernel/wakeup_reasons/last_resume_reason") - e13dbc7c69cd ("ANDROID: power: wakeup_reason: rename irq_count to irqcount")] -Signed-off-by: Amit Pundir -[astrachan: Folded the following changes into this patch: - 39d7c7fe91c0 ("ANDROID: power: wakeup_reason: Add guard condition for maximum wakeup reasons") - 0730434bdf49 ("ANDROID: power: wakeup_reason: Avoids bogus error messages for the suspend aborts.") - 4e42dceae54e ("ANDROID: power: wakeup_reason: Adds functionality to log the last suspend abort reason.") - f21313b70ac7 ("ANDROID: power: wakeup_reason: Report suspend times from last_suspend_time") - f97ec34442ac ("ANDROID: power: wakeup_reason: fix suspend time reporting") - cd92df73e504 ("ANDROID: power: wakeup: Add last wake up source logging for suspend abort reason.") - 546b6ae3c087 ("ANDROID: power: wakeup: Add the guard condition for len in pm_get_active_wakeup_sources") - 1453d9ffcdbe ("ANDROID: power: wakeup_reason: make logging work in an interrupt context.")] -Change-Id: I81addaf420f1338255c5d0638b0d244a99d777d1 -Signed-off-by: Alistair Strachan ---- - .../ABI/testing/sysfs-kernel-wakeup_reasons | 16 ++ - drivers/base/power/main.c | 5 + - drivers/base/power/wakeup.c | 32 +++ - drivers/base/syscore.c | 5 +- - include/linux/suspend.h | 1 + - include/linux/wakeup_reason.h | 30 +++ - kernel/power/Makefile | 1 + - kernel/power/process.c | 22 +- - kernel/power/suspend.c | 20 +- - kernel/power/wakeup_reason.c | 215 ++++++++++++++++++ - 10 files changed, 339 insertions(+), 8 deletions(-) - create mode 100644 Documentation/ABI/testing/sysfs-kernel-wakeup_reasons - create mode 100644 include/linux/wakeup_reason.h - create mode 100644 kernel/power/wakeup_reason.c - -diff --git a/Documentation/ABI/testing/sysfs-kernel-wakeup_reasons b/Documentation/ABI/testing/sysfs-kernel-wakeup_reasons -new file mode 100644 -index 000000000000..acb19b91c192 ---- /dev/null -+++ b/Documentation/ABI/testing/sysfs-kernel-wakeup_reasons -@@ -0,0 +1,16 @@ -+What: /sys/kernel/wakeup_reasons/last_resume_reason -+Date: February 2014 -+Contact: Ruchi Kandoi -+Description: -+ The /sys/kernel/wakeup_reasons/last_resume_reason is -+ used to report wakeup reasons after system exited suspend. -+ -+What: /sys/kernel/wakeup_reasons/last_suspend_time -+Date: March 2015 -+Contact: jinqian -+Description: -+ The /sys/kernel/wakeup_reasons/last_suspend_time is -+ used to report time spent in last suspend cycle. It contains -+ two numbers (in seconds) separated by space. First number is -+ the time spent in suspend and resume processes. Second number -+ is the time spent in sleep state. -\ No newline at end of file -diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c -index 134a8af51511..f545b4526172 100644 ---- a/drivers/base/power/main.c -+++ b/drivers/base/power/main.c -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - #include "../base.h" - #include "power.h" -@@ -1683,6 +1684,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) - pm_callback_t callback = NULL; - const char *info = NULL; - int error = 0; -+ char suspend_abort[MAX_SUSPEND_ABORT_LEN]; - DECLARE_DPM_WATCHDOG_ON_STACK(wd); - - TRACE_DEVICE(dev); -@@ -1706,6 +1708,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) - - if (pm_wakeup_pending()) { - dev->power.direct_complete = false; -+ pm_get_active_wakeup_sources(suspend_abort, -+ MAX_SUSPEND_ABORT_LEN); -+ log_suspend_abort_reason(suspend_abort); - async_error = -EBUSY; - goto Complete; - } -diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c -index 5817b51d2b15..06b3ce836a24 100644 ---- a/drivers/base/power/wakeup.c -+++ b/drivers/base/power/wakeup.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - - #include "power.h" -@@ -813,6 +814,37 @@ void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard) - } - EXPORT_SYMBOL_GPL(pm_wakeup_dev_event); - -+void pm_get_active_wakeup_sources(char *pending_wakeup_source, size_t max) -+{ -+ struct wakeup_source *ws, *last_active_ws = NULL; -+ int len = 0; -+ bool active = false; -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(ws, &wakeup_sources, entry) { -+ if (ws->active && len < max) { -+ if (!active) -+ len += scnprintf(pending_wakeup_source, max, -+ "Pending Wakeup Sources: "); -+ len += scnprintf(pending_wakeup_source + len, max - len, -+ "%s ", ws->name); -+ active = true; -+ } else if (!active && -+ (!last_active_ws || -+ ktime_to_ns(ws->last_time) > -+ ktime_to_ns(last_active_ws->last_time))) { -+ last_active_ws = ws; -+ } -+ } -+ if (!active && last_active_ws) { -+ scnprintf(pending_wakeup_source, max, -+ "Last active Wakeup Source: %s", -+ last_active_ws->name); -+ } -+ rcu_read_unlock(); -+} -+EXPORT_SYMBOL_GPL(pm_get_active_wakeup_sources); -+ - void pm_print_active_wakeup_sources(void) - { - struct wakeup_source *ws; -diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c -index 0d346a307140..f3ca20cc817b 100644 ---- a/drivers/base/syscore.c -+++ b/drivers/base/syscore.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - static LIST_HEAD(syscore_ops_list); - static DEFINE_MUTEX(syscore_ops_lock); -@@ -74,7 +75,9 @@ int syscore_suspend(void) - return 0; - - err_out: -- pr_err("PM: System core suspend callback %pS failed.\n", ops->suspend); -+ log_suspend_abort_reason("System core suspend callback %pS failed", -+ ops->suspend); -+ pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend); - - list_for_each_entry_continue(ops, &syscore_ops_list, node) - if (ops->resume) -diff --git a/include/linux/suspend.h b/include/linux/suspend.h -index 6fc8843f1c9e..60113c8a796f 100644 ---- a/include/linux/suspend.h -+++ b/include/linux/suspend.h -@@ -503,6 +503,7 @@ extern bool pm_get_wakeup_count(unsigned int *count, bool block); - extern bool pm_save_wakeup_count(unsigned int count); - extern void pm_wakep_autosleep_enabled(bool set); - extern void pm_print_active_wakeup_sources(void); -+extern void pm_get_active_wakeup_sources(char *pending_sources, size_t max); - - extern void lock_system_sleep(void); - extern void unlock_system_sleep(void); -diff --git a/include/linux/wakeup_reason.h b/include/linux/wakeup_reason.h -new file mode 100644 -index 000000000000..9fbe209c7177 ---- /dev/null -+++ b/include/linux/wakeup_reason.h -@@ -0,0 +1,30 @@ -+/* -+ * include/linux/wakeup_reason.h -+ * -+ * Logs the reason which caused the kernel to resume -+ * from the suspend mode. -+ * -+ * Copyright (C) 2014 Google, Inc. -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ */ -+ -+#ifndef _LINUX_WAKEUP_REASON_H -+#define _LINUX_WAKEUP_REASON_H -+ -+#define MAX_SUSPEND_ABORT_LEN 256 -+ -+void log_wakeup_reason(int irq); -+#ifdef CONFIG_SUSPEND -+void log_suspend_abort_reason(const char *fmt, ...); -+#else -+static inline void log_suspend_abort_reason(const char *fmt, ...) { } -+#endif -+ -+#endif /* _LINUX_WAKEUP_REASON_H */ -diff --git a/kernel/power/Makefile b/kernel/power/Makefile -index e7e47d9be1e5..c673a1b73973 100644 ---- a/kernel/power/Makefile -+++ b/kernel/power/Makefile -@@ -16,4 +16,5 @@ obj-$(CONFIG_PM_WAKELOCKS) += wakelock.o - - obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o - -+obj-$(CONFIG_SUSPEND) += wakeup_reason.o - obj-$(CONFIG_ENERGY_MODEL) += energy_model.o -diff --git a/kernel/power/process.c b/kernel/power/process.c -index 4b6a54da7e65..dfd2494543c1 100644 ---- a/kernel/power/process.c -+++ b/kernel/power/process.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - /* - * Timeout for stopping processes -@@ -38,6 +39,9 @@ static int try_to_freeze_tasks(bool user_only) - unsigned int elapsed_msecs; - bool wakeup = false; - int sleep_usecs = USEC_PER_MSEC; -+#ifdef CONFIG_PM_SLEEP -+ char suspend_abort[MAX_SUSPEND_ABORT_LEN]; -+#endif - - start = ktime_get_boottime(); - -@@ -67,6 +71,11 @@ static int try_to_freeze_tasks(bool user_only) - break; - - if (pm_wakeup_pending()) { -+#ifdef CONFIG_PM_SLEEP -+ pm_get_active_wakeup_sources(suspend_abort, -+ MAX_SUSPEND_ABORT_LEN); -+ log_suspend_abort_reason(suspend_abort); -+#endif - wakeup = true; - break; - } -@@ -85,18 +94,21 @@ static int try_to_freeze_tasks(bool user_only) - elapsed = ktime_sub(end, start); - elapsed_msecs = ktime_to_ms(elapsed); - -- if (todo) { -+ if (wakeup) { - pr_cont("\n"); -- pr_err("Freezing of tasks %s after %d.%03d seconds " -- "(%d tasks refusing to freeze, wq_busy=%d):\n", -- wakeup ? "aborted" : "failed", -+ pr_err("Freezing of tasks aborted after %d.%03d seconds", -+ elapsed_msecs / 1000, elapsed_msecs % 1000); -+ } else if (todo) { -+ pr_cont("\n"); -+ pr_err("Freezing of tasks failed after %d.%03d seconds" -+ " (%d tasks refusing to freeze, wq_busy=%d):\n", - elapsed_msecs / 1000, elapsed_msecs % 1000, - todo - wq_busy, wq_busy); - - if (wq_busy) - show_workqueue_state(); - -- if (!wakeup || pm_debug_messages_on) { -+ if (pm_debug_messages_on) { - read_lock(&tasklist_lock); - for_each_process_thread(g, p) { - if (p != current && !freezer_should_skip(p) -diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c -index f3b7239f1892..de6b24bc0619 100644 ---- a/kernel/power/suspend.c -+++ b/kernel/power/suspend.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include "power.h" - -@@ -389,7 +390,8 @@ void __weak arch_suspend_enable_irqs(void) - */ - static int suspend_enter(suspend_state_t state, bool *wakeup) - { -- int error; -+ char suspend_abort[MAX_SUSPEND_ABORT_LEN]; -+ int error, last_dev; - - error = platform_suspend_prepare(state); - if (error) -@@ -397,7 +399,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) - - error = dpm_suspend_late(PMSG_SUSPEND); - if (error) { -+ last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1; -+ last_dev %= REC_FAILED_NUM; - pr_err("late suspend of devices failed\n"); -+ log_suspend_abort_reason("%s device failed to power down", -+ suspend_stats.failed_devs[last_dev]); - goto Platform_finish; - } - error = platform_suspend_prepare_late(state); -@@ -406,7 +412,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) - - error = dpm_suspend_noirq(PMSG_SUSPEND); - if (error) { -+ last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1; -+ last_dev %= REC_FAILED_NUM; - pr_err("noirq suspend of devices failed\n"); -+ log_suspend_abort_reason("noirq suspend of %s device failed", -+ suspend_stats.failed_devs[last_dev]); - goto Platform_early_resume; - } - error = platform_suspend_prepare_noirq(state); -@@ -422,8 +432,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) - } - - error = suspend_disable_secondary_cpus(); -- if (error || suspend_test(TEST_CPUS)) -+ if (error || suspend_test(TEST_CPUS)) { -+ log_suspend_abort_reason("Disabling non-boot cpus failed"); - goto Enable_cpus; -+ } - - arch_suspend_disable_irqs(); - BUG_ON(!irqs_disabled()); -@@ -440,6 +452,9 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) - trace_suspend_resume(TPS("machine_suspend"), - state, false); - } else if (*wakeup) { -+ pm_get_active_wakeup_sources(suspend_abort, -+ MAX_SUSPEND_ABORT_LEN); -+ log_suspend_abort_reason(suspend_abort); - error = -EBUSY; - } - syscore_resume(); -@@ -494,6 +509,7 @@ int suspend_devices_and_enter(suspend_state_t state) - error = dpm_suspend_start(PMSG_SUSPEND); - if (error) { - pr_err("Some devices failed to suspend, or early wake event detected\n"); -+ log_suspend_abort_reason("Some devices failed to suspend, or early wake event detected"); - goto Recover_platform; - } - suspend_test_finish("suspend devices"); -diff --git a/kernel/power/wakeup_reason.c b/kernel/power/wakeup_reason.c -new file mode 100644 -index 000000000000..3ce5c902e3d3 ---- /dev/null -+++ b/kernel/power/wakeup_reason.c -@@ -0,0 +1,215 @@ -+/* -+ * kernel/power/wakeup_reason.c -+ * -+ * Logs the reasons which caused the kernel to resume from -+ * the suspend mode. -+ * -+ * Copyright (C) 2014 Google, Inc. -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#define MAX_WAKEUP_REASON_IRQS 32 -+static int irq_list[MAX_WAKEUP_REASON_IRQS]; -+static int irqcount; -+static bool suspend_abort; -+static char abort_reason[MAX_SUSPEND_ABORT_LEN]; -+static struct kobject *wakeup_reason; -+static spinlock_t resume_reason_lock; -+ -+static ktime_t last_monotime; /* monotonic time before last suspend */ -+static ktime_t curr_monotime; /* monotonic time after last suspend */ -+static ktime_t last_stime; /* monotonic boottime offset before last suspend */ -+static ktime_t curr_stime; /* monotonic boottime offset after last suspend */ -+ -+static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr, -+ char *buf) -+{ -+ int irq_no, buf_offset = 0; -+ struct irq_desc *desc; -+ unsigned long flags; -+ spin_lock_irqsave(&resume_reason_lock, flags); -+ if (suspend_abort) { -+ buf_offset = sprintf(buf, "Abort: %s", abort_reason); -+ } else { -+ for (irq_no = 0; irq_no < irqcount; irq_no++) { -+ desc = irq_to_desc(irq_list[irq_no]); -+ if (desc && desc->action && desc->action->name) -+ buf_offset += sprintf(buf + buf_offset, "%d %s\n", -+ irq_list[irq_no], desc->action->name); -+ else -+ buf_offset += sprintf(buf + buf_offset, "%d\n", -+ irq_list[irq_no]); -+ } -+ } -+ spin_unlock_irqrestore(&resume_reason_lock, flags); -+ return buf_offset; -+} -+ -+static ssize_t last_suspend_time_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ struct timespec64 sleep_time; -+ struct timespec64 total_time; -+ struct timespec64 suspend_resume_time; -+ -+ /* -+ * total_time is calculated from monotonic bootoffsets because -+ * unlike CLOCK_MONOTONIC it include the time spent in suspend state. -+ */ -+ total_time = ktime_to_timespec64(ktime_sub(curr_stime, last_stime)); -+ -+ /* -+ * suspend_resume_time is calculated as monotonic (CLOCK_MONOTONIC) -+ * time interval before entering suspend and post suspend. -+ */ -+ suspend_resume_time = -+ ktime_to_timespec64(ktime_sub(curr_monotime, last_monotime)); -+ -+ /* sleep_time = total_time - suspend_resume_time */ -+ sleep_time = timespec64_sub(total_time, suspend_resume_time); -+ -+ /* Export suspend_resume_time and sleep_time in pair here. */ -+ return sprintf(buf, "%llu.%09lu %llu.%09lu\n", -+ suspend_resume_time.tv_sec, suspend_resume_time.tv_nsec, -+ sleep_time.tv_sec, sleep_time.tv_nsec); -+} -+ -+static struct kobj_attribute resume_reason = __ATTR_RO(last_resume_reason); -+static struct kobj_attribute suspend_time = __ATTR_RO(last_suspend_time); -+ -+static struct attribute *attrs[] = { -+ &resume_reason.attr, -+ &suspend_time.attr, -+ NULL, -+}; -+static struct attribute_group attr_group = { -+ .attrs = attrs, -+}; -+ -+/* -+ * logs all the wake up reasons to the kernel -+ * stores the irqs to expose them to the userspace via sysfs -+ */ -+void log_wakeup_reason(int irq) -+{ -+ struct irq_desc *desc; -+ unsigned long flags; -+ desc = irq_to_desc(irq); -+ if (desc && desc->action && desc->action->name) -+ printk(KERN_INFO "Resume caused by IRQ %d, %s\n", irq, -+ desc->action->name); -+ else -+ printk(KERN_INFO "Resume caused by IRQ %d\n", irq); -+ -+ spin_lock_irqsave(&resume_reason_lock, flags); -+ if (irqcount == MAX_WAKEUP_REASON_IRQS) { -+ spin_unlock_irqrestore(&resume_reason_lock, flags); -+ printk(KERN_WARNING "Resume caused by more than %d IRQs\n", -+ MAX_WAKEUP_REASON_IRQS); -+ return; -+ } -+ -+ irq_list[irqcount++] = irq; -+ spin_unlock_irqrestore(&resume_reason_lock, flags); -+} -+ -+void log_suspend_abort_reason(const char *fmt, ...) -+{ -+ unsigned long flags; -+ va_list args; -+ -+ spin_lock_irqsave(&resume_reason_lock, flags); -+ -+ //Suspend abort reason has already been logged. -+ if (suspend_abort) { -+ spin_unlock_irqrestore(&resume_reason_lock, flags); -+ return; -+ } -+ -+ suspend_abort = true; -+ va_start(args, fmt); -+ vsnprintf(abort_reason, MAX_SUSPEND_ABORT_LEN, fmt, args); -+ va_end(args); -+ spin_unlock_irqrestore(&resume_reason_lock, flags); -+} -+ -+/* Detects a suspend and clears all the previous wake up reasons*/ -+static int wakeup_reason_pm_event(struct notifier_block *notifier, -+ unsigned long pm_event, void *unused) -+{ -+ unsigned long flags; -+ switch (pm_event) { -+ case PM_SUSPEND_PREPARE: -+ spin_lock_irqsave(&resume_reason_lock, flags); -+ irqcount = 0; -+ suspend_abort = false; -+ spin_unlock_irqrestore(&resume_reason_lock, flags); -+ /* monotonic time since boot */ -+ last_monotime = ktime_get(); -+ /* monotonic time since boot including the time spent in suspend */ -+ last_stime = ktime_get_boottime(); -+ break; -+ case PM_POST_SUSPEND: -+ /* monotonic time since boot */ -+ curr_monotime = ktime_get(); -+ /* monotonic time since boot including the time spent in suspend */ -+ curr_stime = ktime_get_boottime(); -+ break; -+ default: -+ break; -+ } -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block wakeup_reason_pm_notifier_block = { -+ .notifier_call = wakeup_reason_pm_event, -+}; -+ -+/* Initializes the sysfs parameter -+ * registers the pm_event notifier -+ */ -+int __init wakeup_reason_init(void) -+{ -+ int retval; -+ spin_lock_init(&resume_reason_lock); -+ retval = register_pm_notifier(&wakeup_reason_pm_notifier_block); -+ if (retval) -+ printk(KERN_WARNING "[%s] failed to register PM notifier %d\n", -+ __func__, retval); -+ -+ wakeup_reason = kobject_create_and_add("wakeup_reasons", kernel_kobj); -+ if (!wakeup_reason) { -+ printk(KERN_WARNING "[%s] failed to create a sysfs kobject\n", -+ __func__); -+ return 1; -+ } -+ retval = sysfs_create_group(wakeup_reason, &attr_group); -+ if (retval) { -+ kobject_put(wakeup_reason); -+ printk(KERN_WARNING "[%s] failed to create a sysfs group %d\n", -+ __func__, retval); -+ } -+ return 0; -+} -+ -+late_initcall(wakeup_reason_init); diff --git a/patches/ANDROID-proc-Add-proc-uid-directory.patch b/patches/ANDROID-proc-Add-proc-uid-directory.patch deleted file mode 100644 index c6a41602d3ece620f7953e8813d0f98c5e24ef53..0000000000000000000000000000000000000000 --- a/patches/ANDROID-proc-Add-proc-uid-directory.patch +++ /dev/null @@ -1,433 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor O'Brien -Date: Mon, 16 Oct 2017 10:30:24 -0700 -Subject: ANDROID: proc: Add /proc/uid directory - -Add support for reporting per-uid information through procfs, roughly -following the approach used for per-tid and per-tgid directories in -fs/proc/base.c. -This also entails some new tracking of which uids have been used, to -avoid losing information when the last task with a given uid exits. - -Bug: 72339335 -Bug: 127641090 -Test: ls /proc/uid/; compare with UIDs in /proc/uid_time_in_state -Change-Id: I0908f0c04438b11ceb673d860e58441bf503d478 -Signed-off-by: Connor O'Brien -[AmitP: Fix proc_fill_cache() now that upstream commit - 0168b9e38c42 ("procfs: switch instantiate_t to d_splice_alias()"), - switched instantiate() callback to d_splice_alias()] -Signed-off-by: Amit Pundir -[astrachan: Folded 97b7790f505e ("ANDROID: proc: fix undefined behavior - in proc_uid_base_readdir") into this change] -Signed-off-by: Alistair Strachan ---- - fs/proc/Kconfig | 6 + - fs/proc/Makefile | 1 + - fs/proc/internal.h | 9 ++ - fs/proc/root.c | 1 + - fs/proc/uid.c | 290 ++++++++++++++++++++++++++++++++++++++++ - include/linux/proc_fs.h | 6 + - kernel/user.c | 3 + - 7 files changed, 316 insertions(+) - create mode 100644 fs/proc/uid.c - -diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig -index cb5629bd5fff..313ae27bb674 100644 ---- a/fs/proc/Kconfig -+++ b/fs/proc/Kconfig -@@ -103,3 +103,9 @@ config PROC_CHILDREN - config PROC_PID_ARCH_STATUS - def_bool n - depends on PROC_FS -+ -+config PROC_UID -+ bool "Include /proc/uid/ files" -+ depends on PROC_FS && RT_MUTEXES -+ help -+ Provides aggregated per-uid information under /proc/uid. -diff --git a/fs/proc/Makefile b/fs/proc/Makefile -index ead487e80510..3f849ca0edce 100644 ---- a/fs/proc/Makefile -+++ b/fs/proc/Makefile -@@ -27,6 +27,7 @@ proc-y += softirqs.o - proc-y += namespaces.o - proc-y += self.o - proc-y += thread_self.o -+proc-$(CONFIG_PROC_UID) += uid.o - proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o - proc-$(CONFIG_NET) += proc_net.o - proc-$(CONFIG_PROC_KCORE) += kcore.o -diff --git a/fs/proc/internal.h b/fs/proc/internal.h -index cd0c8d5ce9a1..95846552ef24 100644 ---- a/fs/proc/internal.h -+++ b/fs/proc/internal.h -@@ -253,6 +253,15 @@ static inline void proc_sys_evict_inode(struct inode *inode, - struct ctl_table_header *head) { } - #endif - -+/* -+ * uid.c -+ */ -+#ifdef CONFIG_PROC_UID -+extern int proc_uid_init(void); -+#else -+static inline void proc_uid_init(void) { } -+#endif -+ - /* - * proc_tty.c - */ -diff --git a/fs/proc/root.c b/fs/proc/root.c -index 0b7c8dffc9ae..485237e7cce1 100644 ---- a/fs/proc/root.c -+++ b/fs/proc/root.c -@@ -221,6 +221,7 @@ void __init proc_root_init(void) - proc_symlink("mounts", NULL, "self/mounts"); - - proc_net_init(); -+ proc_uid_init(); - proc_mkdir("fs", NULL); - proc_mkdir("driver", NULL); - proc_create_mount_point("fs/nfsd"); /* somewhere for the nfsd filesystem to be mounted */ -diff --git a/fs/proc/uid.c b/fs/proc/uid.c -new file mode 100644 -index 000000000000..ae720b93a0ed ---- /dev/null -+++ b/fs/proc/uid.c -@@ -0,0 +1,290 @@ -+/* -+ * /proc/uid support -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "internal.h" -+ -+static struct proc_dir_entry *proc_uid; -+ -+#define UID_HASH_BITS 10 -+ -+static DECLARE_HASHTABLE(proc_uid_hash_table, UID_HASH_BITS); -+ -+/* -+ * use rt_mutex here to avoid priority inversion between high-priority readers -+ * of these files and tasks calling proc_register_uid(). -+ */ -+static DEFINE_RT_MUTEX(proc_uid_lock); /* proc_uid_hash_table */ -+ -+struct uid_hash_entry { -+ uid_t uid; -+ struct hlist_node hash; -+}; -+ -+/* Caller must hold proc_uid_lock */ -+static bool uid_hash_entry_exists_locked(uid_t uid) -+{ -+ struct uid_hash_entry *entry; -+ -+ hash_for_each_possible(proc_uid_hash_table, entry, hash, uid) { -+ if (entry->uid == uid) -+ return true; -+ } -+ return false; -+} -+ -+void proc_register_uid(kuid_t kuid) -+{ -+ struct uid_hash_entry *entry; -+ bool exists; -+ uid_t uid = from_kuid_munged(current_user_ns(), kuid); -+ -+ rt_mutex_lock(&proc_uid_lock); -+ exists = uid_hash_entry_exists_locked(uid); -+ rt_mutex_unlock(&proc_uid_lock); -+ if (exists) -+ return; -+ -+ entry = kzalloc(sizeof(struct uid_hash_entry), GFP_KERNEL); -+ if (!entry) -+ return; -+ entry->uid = uid; -+ -+ rt_mutex_lock(&proc_uid_lock); -+ if (uid_hash_entry_exists_locked(uid)) -+ kfree(entry); -+ else -+ hash_add(proc_uid_hash_table, &entry->hash, uid); -+ rt_mutex_unlock(&proc_uid_lock); -+} -+ -+struct uid_entry { -+ const char *name; -+ int len; -+ umode_t mode; -+ const struct inode_operations *iop; -+ const struct file_operations *fop; -+}; -+ -+#define NOD(NAME, MODE, IOP, FOP) { \ -+ .name = (NAME), \ -+ .len = sizeof(NAME) - 1, \ -+ .mode = MODE, \ -+ .iop = IOP, \ -+ .fop = FOP, \ -+} -+ -+static const struct uid_entry uid_base_stuff[] = {}; -+ -+static const struct inode_operations proc_uid_def_inode_operations = { -+ .setattr = proc_setattr, -+}; -+ -+static struct inode *proc_uid_make_inode(struct super_block *sb, kuid_t kuid) -+{ -+ struct inode *inode; -+ -+ inode = new_inode(sb); -+ if (!inode) -+ return NULL; -+ -+ inode->i_ino = get_next_ino(); -+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); -+ inode->i_op = &proc_uid_def_inode_operations; -+ inode->i_uid = kuid; -+ -+ return inode; -+} -+ -+static struct dentry *proc_uident_instantiate(struct dentry *dentry, -+ struct task_struct *unused, const void *ptr) -+{ -+ const struct uid_entry *u = ptr; -+ struct inode *inode; -+ -+ uid_t uid = name_to_int(&dentry->d_name); -+ kuid_t kuid; -+ bool uid_exists; -+ rt_mutex_lock(&proc_uid_lock); -+ uid_exists = uid_hash_entry_exists_locked(uid); -+ rt_mutex_unlock(&proc_uid_lock); -+ if (uid_exists) { -+ kuid = make_kuid(current_user_ns(), uid); -+ inode = proc_uid_make_inode(dentry->d_sb, kuid); -+ if (!inode) -+ return ERR_PTR(-ENOENT); -+ } else { -+ return ERR_PTR(-ENOENT); -+ } -+ -+ inode->i_mode = u->mode; -+ if (S_ISDIR(inode->i_mode)) -+ set_nlink(inode, 2); -+ if (u->iop) -+ inode->i_op = u->iop; -+ if (u->fop) -+ inode->i_fop = u->fop; -+ -+ return d_splice_alias(inode, dentry); -+} -+ -+static struct dentry *proc_uid_base_lookup(struct inode *dir, -+ struct dentry *dentry, -+ unsigned int flags) -+{ -+ const struct uid_entry *u, *last; -+ unsigned int nents = ARRAY_SIZE(uid_base_stuff); -+ -+ if (nents == 0) -+ return ERR_PTR(-ENOENT); -+ -+ last = &uid_base_stuff[nents - 1]; -+ for (u = uid_base_stuff; u <= last; u++) { -+ if (u->len != dentry->d_name.len) -+ continue; -+ if (!memcmp(dentry->d_name.name, u->name, u->len)) -+ break; -+ } -+ if (u > last) -+ return ERR_PTR(-ENOENT); -+ -+ return proc_uident_instantiate(dentry, NULL, u); -+} -+ -+static int proc_uid_base_readdir(struct file *file, struct dir_context *ctx) -+{ -+ unsigned int nents = ARRAY_SIZE(uid_base_stuff); -+ const struct uid_entry *u; -+ -+ if (!dir_emit_dots(file, ctx)) -+ return 0; -+ -+ if (ctx->pos >= nents + 2) -+ return 0; -+ -+ for (u = uid_base_stuff + (ctx->pos - 2); -+ u < uid_base_stuff + nents; u++) { -+ if (!proc_fill_cache(file, ctx, u->name, u->len, -+ proc_uident_instantiate, NULL, u)) -+ break; -+ ctx->pos++; -+ } -+ -+ return 0; -+} -+ -+static const struct inode_operations proc_uid_base_inode_operations = { -+ .lookup = proc_uid_base_lookup, -+ .setattr = proc_setattr, -+}; -+ -+static const struct file_operations proc_uid_base_operations = { -+ .read = generic_read_dir, -+ .iterate = proc_uid_base_readdir, -+ .llseek = default_llseek, -+}; -+ -+static struct dentry *proc_uid_instantiate(struct dentry *dentry, -+ struct task_struct *unused, const void *ptr) -+{ -+ unsigned int i, len; -+ nlink_t nlinks; -+ kuid_t *kuid = (kuid_t *)ptr; -+ struct inode *inode = proc_uid_make_inode(dentry->d_sb, *kuid); -+ -+ if (!inode) -+ return ERR_PTR(-ENOENT); -+ -+ inode->i_mode = S_IFDIR | 0555; -+ inode->i_op = &proc_uid_base_inode_operations; -+ inode->i_fop = &proc_uid_base_operations; -+ inode->i_flags |= S_IMMUTABLE; -+ -+ nlinks = 2; -+ len = ARRAY_SIZE(uid_base_stuff); -+ for (i = 0; i < len; ++i) { -+ if (S_ISDIR(uid_base_stuff[i].mode)) -+ ++nlinks; -+ } -+ set_nlink(inode, nlinks); -+ -+ return d_splice_alias(inode, dentry); -+} -+ -+static int proc_uid_readdir(struct file *file, struct dir_context *ctx) -+{ -+ int last_shown, i; -+ unsigned long bkt; -+ struct uid_hash_entry *entry; -+ -+ if (!dir_emit_dots(file, ctx)) -+ return 0; -+ -+ i = 0; -+ last_shown = ctx->pos - 2; -+ rt_mutex_lock(&proc_uid_lock); -+ hash_for_each(proc_uid_hash_table, bkt, entry, hash) { -+ int len; -+ char buf[PROC_NUMBUF]; -+ -+ if (i < last_shown) -+ continue; -+ len = snprintf(buf, sizeof(buf), "%u", entry->uid); -+ if (!proc_fill_cache(file, ctx, buf, len, -+ proc_uid_instantiate, NULL, &entry->uid)) -+ break; -+ i++; -+ ctx->pos++; -+ } -+ rt_mutex_unlock(&proc_uid_lock); -+ return 0; -+} -+ -+static struct dentry *proc_uid_lookup(struct inode *dir, struct dentry *dentry, -+ unsigned int flags) -+{ -+ int result = -ENOENT; -+ -+ uid_t uid = name_to_int(&dentry->d_name); -+ bool uid_exists; -+ -+ rt_mutex_lock(&proc_uid_lock); -+ uid_exists = uid_hash_entry_exists_locked(uid); -+ rt_mutex_unlock(&proc_uid_lock); -+ if (uid_exists) { -+ kuid_t kuid = make_kuid(current_user_ns(), uid); -+ -+ return proc_uid_instantiate(dentry, NULL, &kuid); -+ } -+ return ERR_PTR(result); -+} -+ -+static const struct file_operations proc_uid_operations = { -+ .read = generic_read_dir, -+ .iterate = proc_uid_readdir, -+ .llseek = default_llseek, -+}; -+ -+static const struct inode_operations proc_uid_inode_operations = { -+ .lookup = proc_uid_lookup, -+ .setattr = proc_setattr, -+}; -+ -+int __init proc_uid_init(void) -+{ -+ proc_uid = proc_mkdir("uid", NULL); -+ if (!proc_uid) -+ return -ENOMEM; -+ proc_uid->proc_iops = &proc_uid_inode_operations; -+ proc_uid->proc_fops = &proc_uid_operations; -+ -+ return 0; -+} -diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h -index a705aa2d03f9..35e83f86e51a 100644 ---- a/include/linux/proc_fs.h -+++ b/include/linux/proc_fs.h -@@ -131,6 +131,12 @@ static inline struct pid *tgid_pidfd_to_pid(const struct file *file) - - #endif /* CONFIG_PROC_FS */ - -+#ifdef CONFIG_PROC_UID -+extern void proc_register_uid(kuid_t uid); -+#else -+static inline void proc_register_uid(kuid_t uid) {} -+#endif -+ - struct net; - - static inline struct proc_dir_entry *proc_net_mkdir( -diff --git a/kernel/user.c b/kernel/user.c -index 5235d7f49982..a32a8a59a13c 100644 ---- a/kernel/user.c -+++ b/kernel/user.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - - /* -@@ -205,6 +206,7 @@ struct user_struct *alloc_uid(kuid_t uid) - } - spin_unlock_irq(&uidhash_lock); - } -+ proc_register_uid(uid); - - return up; - } -@@ -223,6 +225,7 @@ static int __init uid_cache_init(void) - spin_lock_irq(&uidhash_lock); - uid_hash_insert(&root_user, uidhashentry(GLOBAL_ROOT_UID)); - spin_unlock_irq(&uidhash_lock); -+ proc_register_uid(GLOBAL_ROOT_UID); - - return 0; - } diff --git a/patches/ANDROID-refactor-build.config-files-to-remove-duplication.patch b/patches/ANDROID-refactor-build.config-files-to-remove-duplication.patch deleted file mode 100644 index 81b688b3a9362cbf53a7d69d20df0035b004764e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-refactor-build.config-files-to-remove-duplication.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthias Maennich -Date: Thu, 29 Aug 2019 12:34:52 +0100 -Subject: ANDROID: refactor build.config files to remove duplication - -The build.config.* files largely contain duplicate information by their -nature. Reorganize them reduce duplication and to allow adding new -configurations without copying the definitions again. - -Bug: 140224784 -Change-Id: I6a3810a125b0ed48591690ca33bb5c02be58218a -Signed-off-by: Matthias Maennich ---- - build.config.aarch64 | 11 +++++++++++ - build.config.common | 9 +++++++++ - build.config.gki | 4 ++++ - build.config.gki.x86_64 | 23 ++++------------------- - build.config.x86_64 | 11 +++++++++++ - 5 files changed, 39 insertions(+), 19 deletions(-) - create mode 100644 build.config.aarch64 - create mode 100644 build.config.common - create mode 100644 build.config.gki - create mode 100644 build.config.x86_64 - -diff --git a/build.config.aarch64 b/build.config.aarch64 -new file mode 100644 -index 000000000000..523bbc0449f7 ---- /dev/null -+++ b/build.config.aarch64 -@@ -0,0 +1,11 @@ -+ARCH=arm64 -+ -+CLANG_TRIPLE=aarch64-linux-gnu- -+CROSS_COMPILE=aarch64-linux-androidkernel- -+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin -+ -+FILES=" -+arch/arm64/boot/Image.gz -+vmlinux -+System.map -+" -diff --git a/build.config.common b/build.config.common -new file mode 100644 -index 000000000000..3f1fac231a82 ---- /dev/null -+++ b/build.config.common -@@ -0,0 +1,9 @@ -+BRANCH=android-mainline -+KERNEL_DIR=common -+ -+CC=clang -+CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin -+BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 -+ -+EXTRA_CMDS='' -+STOP_SHIP_TRACEPRINTK=1 -diff --git a/build.config.gki b/build.config.gki -new file mode 100644 -index 000000000000..66f6eb8baadb ---- /dev/null -+++ b/build.config.gki -@@ -0,0 +1,4 @@ -+DEFCONFIG=gki_defconfig -+POST_DEFCONFIG_CMDS="check_defconfig" -+BUILD_INITRAMFS=1 -+ -diff --git a/build.config.gki.x86_64 b/build.config.gki.x86_64 -index 5c2db37a2871..627d1e1c27ab 100644 ---- a/build.config.gki.x86_64 -+++ b/build.config.gki.x86_64 -@@ -1,19 +1,4 @@ --ARCH=x86_64 --BRANCH=android-mainline --CLANG_TRIPLE=x86_64-linux-gnu- --CROSS_COMPILE=x86_64-linux-androidkernel- --CC=clang --DEFCONFIG=gki_defconfig --EXTRA_CMDS='' --KERNEL_DIR=common --POST_DEFCONFIG_CMDS="check_defconfig" --CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r353983c/bin --BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 --LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin --FILES=" --arch/x86/boot/bzImage --vmlinux --System.map --" --STOP_SHIP_TRACEPRINTK=1 --BUILD_INITRAMFS=1 -+. ${ROOT_DIR}/common/build.config.common -+. ${ROOT_DIR}/common/build.config.x86_64 -+. ${ROOT_DIR}/common/build.config.gki -+ -diff --git a/build.config.x86_64 b/build.config.x86_64 -new file mode 100644 -index 000000000000..df73a47e7220 ---- /dev/null -+++ b/build.config.x86_64 -@@ -0,0 +1,11 @@ -+ARCH=x86_64 -+ -+CLANG_TRIPLE=x86_64-linux-gnu- -+CROSS_COMPILE=x86_64-linux-androidkernel- -+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin -+ -+FILES=" -+arch/x86/boot/bzImage -+vmlinux -+System.map -+" diff --git a/patches/ANDROID-sched-Honor-sync-flag-for-energy-aware-wakeups.patch b/patches/ANDROID-sched-Honor-sync-flag-for-energy-aware-wakeups.patch deleted file mode 100644 index 0e51f4e02b7568e42a1361cbd872e61d141da262..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-Honor-sync-flag-for-energy-aware-wakeups.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Redpath -Date: Thu, 17 Oct 2019 11:18:08 +0100 -Subject: ANDROID: sched: Honor sync flag for energy-aware wakeups - -Since we don't do energy-aware wakeups when we are overutilized, always -honoring sync wakeups in this state does not prevent wake-wide mechanics -overruling the flag as normal. - -Having the check for (cpu_rq(cpu)->nr_running == 1) in the test condition -means that we only bypass the energy model for sync wakeups where the -cpu is about to become idle. This matches the use of this flag in Binder -which is the main place where sync wakeups come from in Android. - -This patch is based upon previous work to build EAS for android products. -It replaces -commit 79e3a4a27ee5 ("ANDROID: sched: Unconditionally honor sync flag - for energy-aware wakeups") -in what's considered to be 'EAS'. - -sync-hint code taken from wahoo -https://android.googlesource.com/kernel/msm/+/4a5e890ec60d -written by Juri Lelli - -Change-Id: I4b3d79141fc8e53dc51cd63ac11096c2e3cb10f5 -Signed-off-by: Chris Redpath -(cherry-picked from commit f1ec666a62de) -[ Moved the feature to find_energy_efficient_cpu() and removed the - sysctl knob ] -Signed-off-by: Quentin Perret -[ Add 'cpu_rq(cpu)->nr_running == 1' to the condition and remove the - word 'Unconditionally' from the patch name ] -Signed-off-by: Dietmar Eggemann ---- - kernel/sched/fair.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index ba1eaa599dbc..8f8692baa679 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -6364,7 +6364,8 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy - goto fail; - - cpu = smp_processor_id(); -- if (sync && cpumask_test_cpu(cpu, p->cpus_ptr)) { -+ if (sync && cpu_rq(cpu)->nr_running == 1 && -+ cpumask_test_cpu(cpu, p->cpus_ptr)) { - rcu_read_unlock(); - return cpu; - } diff --git a/patches/ANDROID-sched-Introduce-uclamp-latency-and-boost-wrapper.patch b/patches/ANDROID-sched-Introduce-uclamp-latency-and-boost-wrapper.patch deleted file mode 100644 index 552fbd9a44fa5619c54d087f7659cdae0bf2e42e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-Introduce-uclamp-latency-and-boost-wrapper.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Quentin Perret -Date: Tue, 30 Jul 2019 13:58:29 +0100 -Subject: ANDROID: sched: Introduce uclamp latency and boost wrapper - -Introduce a simple helper to read the latency_sensitive flag from a -task. It is called uclamp_latency_sensitive() to match the API -proposed by Patrick. - -While at it, introduce uclamp_boosted() which returns true only when a -task has a non-null min-clamp. - -Change-Id: I5fc747da8b58625257a6604a3c88487b657fbe7a -Suggested-by: Patrick Bellasi -Signed-off-by: Quentin Perret ---- - kernel/sched/sched.h | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index 7de9f16cb838..4f0d1668c283 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -2333,6 +2333,11 @@ static inline unsigned int uclamp_util(struct rq *rq, unsigned int util) - { - return uclamp_util_with(rq, util, NULL); - } -+ -+static inline bool uclamp_boosted(struct task_struct *p) -+{ -+ return uclamp_eff_value(p, UCLAMP_MIN) > 0; -+} - #else /* CONFIG_UCLAMP_TASK */ - static inline unsigned int uclamp_util_with(struct rq *rq, unsigned int util, - struct task_struct *p) -@@ -2343,8 +2348,31 @@ static inline unsigned int uclamp_util(struct rq *rq, unsigned int util) - { - return util; - } -+static inline bool uclamp_boosted(struct task_struct *p) -+{ -+ return false; -+} - #endif /* CONFIG_UCLAMP_TASK */ - -+#ifdef CONFIG_UCLAMP_TASK_GROUP -+static inline bool uclamp_latency_sensitive(struct task_struct *p) -+{ -+ struct cgroup_subsys_state *css = task_css(p, cpu_cgrp_id); -+ struct task_group *tg; -+ -+ if (!css) -+ return false; -+ tg = container_of(css, struct task_group, css); -+ -+ return tg->latency_sensitive; -+} -+#else -+static inline bool uclamp_latency_sensitive(struct task_struct *p) -+{ -+ return false; -+} -+#endif /* CONFIG_UCLAMP_TASK_GROUP */ -+ - #ifdef arch_scale_freq_capacity - # ifndef arch_scale_freq_invariant - # define arch_scale_freq_invariant() true diff --git a/patches/ANDROID-sched-Prevent-unnecessary-active-balance-of-single-task-in-sched-group.patch b/patches/ANDROID-sched-Prevent-unnecessary-active-balance-of-single-task-in-sched-group.patch deleted file mode 100644 index 19d240f9ef0f66284ab14b2f3b8b4f1617d5d2fc..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-Prevent-unnecessary-active-balance-of-single-task-in-sched-group.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Morten Rasmussen -Date: Thu, 2 Jul 2015 17:16:34 +0100 -Subject: ANDROID: sched: Prevent unnecessary active balance of single task in - sched group - -Scenarios with the busiest group having just one task and the local -being idle on topologies with sched groups with different numbers of -cpus manage to dodge all load-balance bailout conditions resulting the -nr_balance_failed counter to be incremented. This eventually causes a -pointless active migration of the task. This patch prevents this by not -incrementing the counter when the busiest group only has one task. -ASYM_PACKING migrations and migrations due to reduced capacity should -still take place as these are explicitly captured by -need_active_balance(). - -A better solution would be to not attempt the load-balance in the first -place, but that requires significant changes to the order of bailout -conditions and statistics gathering. - -Change-Id: I28f69c72febe0211decbe77b7bc3e48839d3d7b3 -cc: Ingo Molnar -cc: Peter Zijlstra -Signed-off-by: Morten Rasmussen -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index f0631d17c0bf..b62581b58f13 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -7120,6 +7120,7 @@ struct lb_env { - int new_dst_cpu; - enum cpu_idle_type idle; - long imbalance; -+ unsigned int src_grp_nr_running; - /* The set of CPUs under consideration for load-balancing */ - struct cpumask *cpus; - -@@ -8302,6 +8303,8 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd - if (env->sd->flags & SD_NUMA) - env->fbq_type = fbq_classify_group(&sds->busiest_stat); - -+ env->src_grp_nr_running = sds->busiest_stat.sum_nr_running; -+ - if (!env->sd->parent) { - struct root_domain *rd = env->dst_rq->rd; - -@@ -8996,7 +8999,8 @@ static int load_balance(int this_cpu, struct rq *this_rq, - * excessive cache_hot migrations and active balances. - */ - if (idle != CPU_NEWLY_IDLE) -- sd->nr_balance_failed++; -+ if (env.src_grp_nr_running > 1) -+ sd->nr_balance_failed++; - - if (need_active_balance(&env)) { - unsigned long flags; diff --git a/patches/ANDROID-sched-Unconditionally-honor-sync-flag-for-energy-aware-wakeups.patch b/patches/ANDROID-sched-Unconditionally-honor-sync-flag-for-energy-aware-wakeups.patch deleted file mode 100644 index 24d18deb0a67236d9b4f0ca94080f4b7ef768941..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-Unconditionally-honor-sync-flag-for-energy-aware-wakeups.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Redpath -Date: Wed, 27 Mar 2019 17:15:17 +0000 -Subject: ANDROID: sched: Unconditionally honor sync flag for energy-aware - wakeups - -Since we don't do energy-aware wakeups when we are overutilized, always -honoring sync wakeups in this state does not prevent wake-wide mechanics -overruling the flag as normal. - -This patch is based upon previous work to build EAS for android products. - -sync-hint code taken from commit 4a5e890ec60d -"sched/fair: add tunable to force selection at cpu granularity" written -by Juri Lelli - -Change-Id: I4b3d79141fc8e53dc51cd63ac11096c2e3cb10f5 -Signed-off-by: Chris Redpath -(cherry-picked from commit f1ec666a62dec1083ed52fe1ddef093b84373aaf) -[ Moved the feature to find_energy_efficient_cpu() and removed the - sysctl knob ] -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index 49137eff0c8e..43d3321ce61e 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -6344,7 +6344,7 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd) - * other use-cases too. So, until someone finds a better way to solve this, - * let's keep things simple by re-using the existing slow path. - */ --static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) -+static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sync) - { - unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX; - struct root_domain *rd = cpu_rq(smp_processor_id())->rd; -@@ -6358,6 +6358,12 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) - if (!pd || READ_ONCE(rd->overutilized)) - goto fail; - -+ cpu = smp_processor_id(); -+ if (sync && cpumask_test_cpu(cpu, p->cpus_ptr)) { -+ rcu_read_unlock(); -+ return cpu; -+ } -+ - /* - * Energy-aware wake-up happens on the lowest sched_domain starting - * from sd_asym_cpucapacity spanning over this_cpu and prev_cpu. -@@ -6469,7 +6475,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f - record_wakee(p); - - if (sched_energy_enabled()) { -- new_cpu = find_energy_efficient_cpu(p, prev_cpu); -+ new_cpu = find_energy_efficient_cpu(p, prev_cpu, sync); - if (new_cpu >= 0) - return new_cpu; - new_cpu = prev_cpu; diff --git a/patches/ANDROID-sched-Update-max-cpu-capacity-in-case-of-max-frequency-constraints.patch b/patches/ANDROID-sched-Update-max-cpu-capacity-in-case-of-max-frequency-constraints.patch deleted file mode 100644 index 31edbbd463387290ad20a23f46f4c76407ff2a10..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-Update-max-cpu-capacity-in-case-of-max-frequency-constraints.patch +++ /dev/null @@ -1,219 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dietmar Eggemann -Date: Sat, 26 Sep 2015 18:19:54 +0100 -Subject: ANDROID: sched: Update max cpu capacity in case of max frequency - constraints - -Wakeup balancing uses cpu capacity awareness and needs to know the -system-wide maximum cpu capacity. - -Patch "sched: Store system-wide maximum cpu capacity in root domain" -finds the system-wide maximum cpu capacity during scheduler domain -hierarchy setup. This is sufficient as long as maximum frequency -invariance is not enabled. - -If it is enabled, the system-wide maximum cpu capacity can change -between scheduler domain hierarchy setups due to frequency capping. - -The cpu capacity is changed in update_cpu_capacity() which is called in -load balance on the lowest scheduler domain hierarchy level. To be able -to know if a change in cpu capacity for a certain cpu also has an effect -on the system-wide maximum cpu capacity it is normally necessary to -iterate over all cpus. This would be way too costly. That's why this -patch follows a different approach. - -The unsigned long max_cpu_capacity value in struct root_domain is -replaced with a struct max_cpu_capacity, containing value (the -max_cpu_capacity) and cpu (the cpu index of the cpu providing the -maximum cpu_capacity). - -Changes to the system-wide maximum cpu capacity and the cpu index are -made if: - - 1 System-wide maximum cpu capacity < cpu capacity - 2 System-wide maximum cpu capacity > cpu capacity and cpu index == cpu - -There are no changes to the system-wide maximum cpu capacity in all -other cases. - -Atomic read and write access to the pair (max_cpu_capacity.val, -max_cpu_capacity.cpu) is enforced by max_cpu_capacity.lock. - -The access to max_cpu_capacity.val in task_fits_max() is still performed -without taking the max_cpu_capacity.lock. - -The code to set max cpu capacity in build_sched_domains() has been -removed because the whole functionality is now provided by -update_cpu_capacity() instead. - -This approach can introduce errors temporarily, e.g. in case the cpu -currently providing the max cpu capacity has its cpu capacity lowered -due to frequency capping and calls update_cpu_capacity() before any cpu -which might provide the max cpu now. - -Change-Id: I5063befab088fbf49e5d5e484ce0c6ee6165283a -Signed-off-by: Ionela Voinescu * -Signed-off-by: Dietmar Eggemann -(- Fixed cherry-pick issues, and conflict with a0fe2cf086ae "sched/fair: - Tune down misfit NOHZ kicks" which makes use of max_cpu_capacity - - Squashed "sched/fair: remove printk while schedule is in progress" - fix from Caesar Wang ) -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 34 ++++++++++++++++++++++++++++++++-- - kernel/sched/sched.h | 10 +++++++++- - kernel/sched/topology.c | 15 +++------------ - 3 files changed, 44 insertions(+), 15 deletions(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index c0b1c1233727..f0631d17c0bf 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -6203,7 +6203,7 @@ static int wake_cap(struct task_struct *p, int cpu, int prev_cpu) - return 0; - - min_cap = min(capacity_orig_of(prev_cpu), capacity_orig_of(cpu)); -- max_cap = cpu_rq(cpu)->rd->max_cpu_capacity; -+ max_cap = cpu_rq(cpu)->rd->max_cpu_capacity.val; - - /* Minimum capacity is close to max, no need to abort wake_affine */ - if (max_cap - min_cap < max_cap >> 3) -@@ -7755,16 +7755,46 @@ static unsigned long scale_rt_capacity(int cpu, unsigned long max) - return scale_irq_capacity(free, irq, max); - } - -+void init_max_cpu_capacity(struct max_cpu_capacity *mcc) { -+ raw_spin_lock_init(&mcc->lock); -+ mcc->val = 0; -+ mcc->cpu = -1; -+} -+ - static void update_cpu_capacity(struct sched_domain *sd, int cpu) - { - unsigned long capacity = arch_scale_cpu_capacity(cpu); - struct sched_group *sdg = sd->groups; -+ struct max_cpu_capacity *mcc; -+ unsigned long max_capacity; -+ int max_cap_cpu; -+ unsigned long flags; - - cpu_rq(cpu)->cpu_capacity_orig = capacity; - - capacity *= arch_scale_max_freq_capacity(sd, cpu); - capacity >>= SCHED_CAPACITY_SHIFT; - -+ mcc = &cpu_rq(cpu)->rd->max_cpu_capacity; -+ -+ raw_spin_lock_irqsave(&mcc->lock, flags); -+ max_capacity = mcc->val; -+ max_cap_cpu = mcc->cpu; -+ -+ if ((max_capacity > capacity && max_cap_cpu == cpu) || -+ (max_capacity < capacity)) { -+ mcc->val = capacity; -+ mcc->cpu = cpu; -+#ifdef CONFIG_SCHED_DEBUG -+ raw_spin_unlock_irqrestore(&mcc->lock, flags); -+ printk_deferred(KERN_INFO "CPU%d: update max cpu_capacity %lu\n", -+ cpu, capacity); -+ goto skip_unlock; -+#endif -+ } -+ raw_spin_unlock_irqrestore(&mcc->lock, flags); -+ -+skip_unlock: __attribute__ ((unused)); - capacity = scale_rt_capacity(cpu, capacity); - - if (!capacity) -@@ -7869,7 +7899,7 @@ check_cpu_capacity(struct rq *rq, struct sched_domain *sd) - static inline int check_misfit_status(struct rq *rq, struct sched_domain *sd) - { - return rq->misfit_task_load && -- (rq->cpu_capacity_orig < rq->rd->max_cpu_capacity || -+ (rq->cpu_capacity_orig < rq->rd->max_cpu_capacity.val || - check_cpu_capacity(rq, sd)); - } - -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index f0b6e3ab2c96..9015c687de19 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -717,6 +717,12 @@ struct perf_domain { - struct rcu_head rcu; - }; - -+struct max_cpu_capacity { -+ raw_spinlock_t lock; -+ unsigned long val; -+ int cpu; -+}; -+ - /* Scheduling group status flags */ - #define SG_OVERLOAD 0x1 /* More than one runnable task on a CPU. */ - #define SG_OVERUTILIZED 0x2 /* One or more CPUs are over-utilized. */ -@@ -775,7 +781,8 @@ struct root_domain { - cpumask_var_t rto_mask; - struct cpupri cpupri; - -- unsigned long max_cpu_capacity; -+ /* Maximum cpu capacity in the system. */ -+ struct max_cpu_capacity max_cpu_capacity; - - /* - * NULL-terminated list of performance domains intersecting with the -@@ -785,6 +792,7 @@ struct root_domain { - }; - - extern void init_defrootdomain(void); -+extern void init_max_cpu_capacity(struct max_cpu_capacity *mcc); - extern int sched_init_domains(const struct cpumask *cpu_map); - extern void rq_attach_root(struct rq *rq, struct root_domain *rd); - extern void sched_get_rd(struct root_domain *rd); -diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c -index b5667a273bf6..4ad1e5194555 100644 ---- a/kernel/sched/topology.c -+++ b/kernel/sched/topology.c -@@ -510,6 +510,9 @@ static int init_rootdomain(struct root_domain *rd) - - if (cpupri_init(&rd->cpupri) != 0) - goto free_cpudl; -+ -+ init_max_cpu_capacity(&rd->max_cpu_capacity); -+ - return 0; - - free_cpudl: -@@ -1951,7 +1954,6 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att - enum s_alloc alloc_state; - struct sched_domain *sd; - struct s_data d; -- struct rq *rq = NULL; - int i, ret = -ENOMEM; - struct sched_domain_topology_level *tl_asym; - bool has_asym = false; -@@ -2014,13 +2016,7 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att - /* Attach the domains */ - rcu_read_lock(); - for_each_cpu(i, cpu_map) { -- rq = cpu_rq(i); - sd = *per_cpu_ptr(d.sd, i); -- -- /* Use READ_ONCE()/WRITE_ONCE() to avoid load/store tearing: */ -- if (rq->cpu_capacity_orig > READ_ONCE(d.rd->max_cpu_capacity)) -- WRITE_ONCE(d.rd->max_cpu_capacity, rq->cpu_capacity_orig); -- - cpu_attach_domain(sd, d.rd, i); - } - rcu_read_unlock(); -@@ -2028,11 +2024,6 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att - if (has_asym) - static_branch_enable_cpuslocked(&sched_asym_cpucapacity); - -- if (rq && sched_debug_enabled) { -- pr_info("root domain span: %*pbl (max cpu_capacity = %lu)\n", -- cpumask_pr_args(cpu_map), rq->rd->max_cpu_capacity); -- } -- - ret = 0; - error: - __free_domain_allocs(&d, alloc_state, cpu_map); diff --git a/patches/ANDROID-sched-core-Add-a-latency-sensitive-flag-to-uclamp.patch b/patches/ANDROID-sched-core-Add-a-latency-sensitive-flag-to-uclamp.patch deleted file mode 100644 index 4be1a7f124416eca5ba3c4ebd418e5c7ce1699ec..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-core-Add-a-latency-sensitive-flag-to-uclamp.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Quentin Perret -Date: Tue, 30 Jul 2019 13:54:00 +0100 -Subject: ANDROID: sched/core: Add a latency-sensitive flag to uclamp - -Add a 'latency_sensitive' flag to uclamp in order to express the need -for some tasks to find a CPU where they can wake-up quickly. This is not -expected to be used without cgroup support, so add solely a cgroup -interface for it. - -As this flag represents a boolean attribute and not an amount of -resources to be shared, it is not clear what the delegation logic should -be. As such, it is kept simple: every new cgroup starts with -latency_sensitive set to false, regardless of the parent. - -In essence, this is similar to SchedTune's prefer-idle flag which was -used in android-4.19 and prior. - -Change-Id: I722d8ecabb428bb7b95a5b54bc70a87f182dde2a -Signed-off-by: Quentin Perret ---- - kernel/sched/core.c | 33 +++++++++++++++++++++++++++++++++ - kernel/sched/sched.h | 2 ++ - 2 files changed, 35 insertions(+) - -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index dd05a378631a..c05d05094e70 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -7327,6 +7327,27 @@ static int cpu_uclamp_max_show(struct seq_file *sf, void *v) - cpu_uclamp_print(sf, UCLAMP_MAX); - return 0; - } -+ -+static int cpu_uclamp_ls_write_u64(struct cgroup_subsys_state *css, -+ struct cftype *cftype, u64 ls) -+{ -+ struct task_group *tg; -+ -+ if (ls > 1) -+ return -EINVAL; -+ tg = css_tg(css); -+ tg->latency_sensitive = (unsigned int) ls; -+ -+ return 0; -+} -+ -+static u64 cpu_uclamp_ls_read_u64(struct cgroup_subsys_state *css, -+ struct cftype *cft) -+{ -+ struct task_group *tg = css_tg(css); -+ -+ return (u64) tg->latency_sensitive; -+} - #endif /* CONFIG_UCLAMP_TASK_GROUP */ - - #ifdef CONFIG_FAIR_GROUP_SCHED -@@ -7687,6 +7708,12 @@ static struct cftype cpu_legacy_files[] = { - .seq_show = cpu_uclamp_max_show, - .write = cpu_uclamp_max_write, - }, -+ { -+ .name = "uclamp.latency_sensitive", -+ .flags = CFTYPE_NOT_ON_ROOT, -+ .read_u64 = cpu_uclamp_ls_read_u64, -+ .write_u64 = cpu_uclamp_ls_write_u64, -+ }, - #endif - { } /* Terminate */ - }; -@@ -7868,6 +7895,12 @@ static struct cftype cpu_files[] = { - .seq_show = cpu_uclamp_max_show, - .write = cpu_uclamp_max_write, - }, -+ { -+ .name = "uclamp.latency_sensitive", -+ .flags = CFTYPE_NOT_ON_ROOT, -+ .read_u64 = cpu_uclamp_ls_read_u64, -+ .write_u64 = cpu_uclamp_ls_write_u64, -+ }, - #endif - { } /* terminate */ - }; -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index 9015c687de19..7de9f16cb838 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -399,6 +399,8 @@ struct task_group { - struct uclamp_se uclamp_req[UCLAMP_CNT]; - /* Effective clamp values used for a task group */ - struct uclamp_se uclamp[UCLAMP_CNT]; -+ /* Latency-sensitive flag used for a task group */ -+ unsigned int latency_sensitive; - #endif - - }; diff --git a/patches/ANDROID-sched-fair-Also-do-misfit-in-overloaded-groups.patch b/patches/ANDROID-sched-fair-Also-do-misfit-in-overloaded-groups.patch deleted file mode 100644 index c987b468edb547d1b98715e0863297b1f0717291..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-fair-Also-do-misfit-in-overloaded-groups.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Redpath -Date: Tue, 5 Jun 2018 12:21:33 +0100 -Subject: ANDROID: sched/fair: Also do misfit in overloaded groups - -If we can classify the group as overloaded, that overrides -any classification as misfit but we may still have misfit -tasks present. Check the rq we're looking at to see if -this is the case. - -Change-Id: Ida8eb66aa625e34de3fe2ee1b0dd8a78926273d8 -Signed-off-by: Chris Redpath -[Removed stray reference to rq_has_misfit] -Signed-off-by: Valentin Schneider -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index 7faaf156b66c..699f8256dc94 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -8806,6 +8806,9 @@ static int need_active_balance(struct lb_env *env) - if (voluntary_active_balance(env)) - return 1; - -+ if (env->src_grp_type == group_overloaded && env->src_rq->misfit_task_load) -+ return 1; -+ - return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2); - } - diff --git a/patches/ANDROID-sched-fair-Attempt-to-improve-throughput-for-asym-cap-systems.patch b/patches/ANDROID-sched-fair-Attempt-to-improve-throughput-for-asym-cap-systems.patch deleted file mode 100644 index 9a40b3a9449868497c498a25a3eb661de37ae7ae..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-fair-Attempt-to-improve-throughput-for-asym-cap-systems.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Redpath -Date: Fri, 1 Jun 2018 20:34:10 +0100 -Subject: ANDROID: sched/fair: Attempt to improve throughput for asym cap - systems - -In some systems the capacity and group weights line up to defeat all the -small imbalance correction conditions in fix_small_imbalance, which can -cause bad task placement. Add a new condition if the existing code can't -see anything to fix: - -If we have asymmetric capacity, and there are more tasks than CPUs in -the busiest group *and* there are less tasks than CPUs in the local group -then we try to pull something. There could be transient small tasks which -prevent this from working, but on the whole it is beneficial for those -systems with inconvenient capacity/cluster size relationships. - -Change-Id: Icf81cde215c082a61f816534b7990ccb70aee409 -Signed-off-by: Chris Redpath -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index b62581b58f13..f9902c86c5b9 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -8433,7 +8433,22 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) - capa_move /= SCHED_CAPACITY_SCALE; - - /* Move if we gain throughput */ -- if (capa_move > capa_now) -+ if (capa_move > capa_now) { -+ env->imbalance = busiest->load_per_task; -+ return; -+ } -+ -+ /* We can't see throughput improvement with the load-based -+ * method, but it is possible depending upon group size and -+ * capacity range that there might still be an underutilized -+ * cpu available in an asymmetric capacity system. Do one last -+ * check just in case. -+ */ -+ if (env->sd->flags & SD_ASYM_CPUCAPACITY && -+ busiest->group_type == group_overloaded && -+ busiest->sum_nr_running > busiest->group_weight && -+ local->sum_nr_running < local->group_weight && -+ local->group_capacity < busiest->group_capacity) - env->imbalance = busiest->load_per_task; - } - diff --git a/patches/ANDROID-sched-fair-Bias-EAS-placement-for-latency.patch b/patches/ANDROID-sched-fair-Bias-EAS-placement-for-latency.patch deleted file mode 100644 index f0898a7c70dd44b5c110a75306b03f31d8353a49..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-fair-Bias-EAS-placement-for-latency.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Quentin Perret -Date: Wed, 27 Feb 2019 11:21:24 +0000 -Subject: ANDROID: sched/fair: Bias EAS placement for latency - -Add to find_energy_efficient_cpu() a latency sensitive case which mimics -what was done for prefer-idle in android-4.19 and before (see [1] for -reference). - -This isn't strictly equivalent to the legacy algorithm but comes real -close, and isn't very invasive. Overall, the idea is to select the -biggest idle CPU we can find for latency-sensitive boosted tasks, and -the smallest CPU where the can fit for latency-sensitive non-boosted -tasks. - -The main differences with the legacy behaviour are the following: - - 1. the policy for 'prefer idle' when there isn't a single idle CPU in - the system is simpler now. We just pick the CPU with the highest - spare capacity; - - 2. the cstate awareness is implemented by minimizing the exit latency - rather than the idle state index. This is how it is done in the slow - path (find_idlest_group_cpu()), it doesn't require us to keep hooks - into CPUIdle, and should actually be better because what we want is - a CPU that can wake up quickly; - - 3. non-latency-sensitive tasks just use the standard mainline - energy-aware wake-up path, which decides the placement using the - Energy Model; - - 4. the 'boosted' and 'latency_sensitive' attributes of a task come from - util_clamp (which now replaces schedtune). - -[1] https://android.googlesource.com/kernel/common.git/+/c27c56105dcaaae54ecc39ef33fbfac87a1486fc - -Change-Id: Ia58516906e9cb5abe08385a8cd088097043d8703 -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 40 ++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 38 insertions(+), 2 deletions(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index 699f8256dc94..ba1eaa599dbc 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -6348,8 +6348,13 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy - { - unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX; - struct root_domain *rd = cpu_rq(smp_processor_id())->rd; -+ int max_spare_cap_cpu_ls = prev_cpu, best_idle_cpu = -1; -+ unsigned long max_spare_cap_ls = 0, target_cap; - unsigned long cpu_cap, util, base_energy = 0; -+ bool boosted, latency_sensitive = false; -+ unsigned int min_exit_lat = UINT_MAX; - int cpu, best_energy_cpu = prev_cpu; -+ struct cpuidle_state *idle; - struct sched_domain *sd; - struct perf_domain *pd; - -@@ -6378,6 +6383,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy - if (!task_util_est(p)) - goto unlock; - -+ latency_sensitive = uclamp_latency_sensitive(p); -+ boosted = uclamp_boosted(p); -+ target_cap = boosted ? 0 : ULONG_MAX; -+ - for (; pd; pd = pd->next) { - unsigned long cur_delta, spare_cap, max_spare_cap = 0; - unsigned long base_energy_pd; -@@ -6402,7 +6411,7 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy - continue; - - /* Always use prev_cpu as a candidate. */ -- if (cpu == prev_cpu) { -+ if (!latency_sensitive && cpu == prev_cpu) { - prev_delta = compute_energy(p, prev_cpu, pd); - prev_delta -= base_energy_pd; - best_delta = min(best_delta, prev_delta); -@@ -6417,10 +6426,34 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy - max_spare_cap = spare_cap; - max_spare_cap_cpu = cpu; - } -+ -+ if (!latency_sensitive) -+ continue; -+ -+ if (idle_cpu(cpu)) { -+ cpu_cap = capacity_orig_of(cpu); -+ if (boosted && cpu_cap < target_cap) -+ continue; -+ if (!boosted && cpu_cap > target_cap) -+ continue; -+ idle = idle_get_state(cpu_rq(cpu)); -+ if (idle && idle->exit_latency > min_exit_lat && -+ cpu_cap == target_cap) -+ continue; -+ -+ if (idle) -+ min_exit_lat = idle->exit_latency; -+ target_cap = cpu_cap; -+ best_idle_cpu = cpu; -+ } else if (spare_cap > max_spare_cap_ls) { -+ max_spare_cap_ls = spare_cap; -+ max_spare_cap_cpu_ls = cpu; -+ } - } - - /* Evaluate the energy impact of using this CPU. */ -- if (max_spare_cap_cpu >= 0 && max_spare_cap_cpu != prev_cpu) { -+ if (!latency_sensitive && max_spare_cap_cpu >= 0 && -+ max_spare_cap_cpu != prev_cpu) { - cur_delta = compute_energy(p, max_spare_cap_cpu, pd); - cur_delta -= base_energy_pd; - if (cur_delta < best_delta) { -@@ -6432,6 +6465,9 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, int sy - unlock: - rcu_read_unlock(); - -+ if (latency_sensitive) -+ return best_idle_cpu >= 0 ? best_idle_cpu : max_spare_cap_cpu_ls; -+ - /* - * Pick the best CPU if prev_cpu cannot be used, or if it saves at - * least 6% of the energy used by prev_cpu. diff --git a/patches/ANDROID-sched-fair-Don-t-balance-misfits-if-it-would-overload-local-group.patch b/patches/ANDROID-sched-fair-Don-t-balance-misfits-if-it-would-overload-local-group.patch deleted file mode 100644 index 9dda1e6414ab60a79d7802097b15d8d179577432..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-fair-Don-t-balance-misfits-if-it-would-overload-local-group.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Chris Redpath -Date: Tue, 5 Jun 2018 11:47:57 +0100 -Subject: ANDROID: sched/fair: Don't balance misfits if it would overload local - group - -When load balancing in a system with misfit tasks present, if we always -pull a misfit task to the local group this can lead to pulling a running -task from a smaller capacity CPUs to a bigger CPU which is busy. In this -situation, the pulled task is likely not to get a chance to run before -an idle balance on another small CPU pulls it back. This penalises the -pulled task as it is stopped for a short amount of time and then likely -relocated to a different CPU (since the original CPU just did a NEWLY_IDLE -balance and reset the periodic interval). - -If we only do this unconditionally for NEWLY_IDLE balance, we can be -sure that any tasks and load which are present on the local group are -related to short-running tasks which we are happy to displace for a -longer running task in a system with misfit tasks present. - -However, other balance types should only pull a task if we think -that the local group is underutilized - checking the number of tasks -gives us a conservative estimate here since if they were short tasks -we would have been doing NEWLY_IDLE balances instead. - -Change-Id: I710add1ab1139482620b6addc8370ad194791beb -Signed-off-by: Chris Redpath -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index f9902c86c5b9..7faaf156b66c 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -8517,8 +8517,18 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s - (sds->avg_load - local->avg_load) * local->group_capacity - ) / SCHED_CAPACITY_SCALE; - -- /* Boost imbalance to allow misfit task to be balanced. */ -- if (busiest->group_type == group_misfit_task) { -+ /* Boost imbalance to allow misfit task to be balanced. -+ * Always do this if we are doing a NEWLY_IDLE balance -+ * on the assumption that any tasks we have must not be -+ * long-running (and hence we cannot rely upon load). -+ * However if we are not idle, we should assume the tasks -+ * we have are longer running and not override load-based -+ * calculations above unless we are sure that the local -+ * group is underutilized. -+ */ -+ if (busiest->group_type == group_misfit_task && -+ (env->idle == CPU_NEWLY_IDLE || -+ local->sum_nr_running < local->group_weight)) { - env->imbalance = max_t(long, env->imbalance, - busiest->group_misfit_task_load); - } diff --git a/patches/ANDROID-sched-fair-EAS-Add-uclamp-support-to-find_energy_efficient_cpu.patch b/patches/ANDROID-sched-fair-EAS-Add-uclamp-support-to-find_energy_efficient_cpu.patch deleted file mode 100644 index d8f74c8d9e4c9d1b5a43f13e8d75adf21a065239..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-fair-EAS-Add-uclamp-support-to-find_energy_efficient_cpu.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Patrick Bellasi -Date: Tue, 18 Dec 2018 10:31:30 +0000 -Subject: ANDROID: sched/fair: EAS: Add uclamp support to - find_energy_efficient_cpu() - -Utilization clamping can be used to boost the utilization of small tasks -or cap that of big tasks. Thus, one of its possible usages is to bias -tasks placement to "promote" small tasks on higher capacity (less energy -efficient) CPUs or "constraint" big tasks on small capacity (more energy -efficient) CPUs. - -When the Energy Aware Scheduler (EAS) looks for the most energy -efficient CPU to run a task on, it currently considers only the -effective utiliation estimated for a task. - -Fix this by adding an additional check to skip CPUs which capacity is -smaller then the task clamped utilization. - -Change-Id: I43fa6fa27e27c1eb5272c6a45d1a6a5b0faae1aa -Signed-off-by: Patrick Bellasi -Cc: Ingo Molnar -Cc: Peter Zijlstra -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index 682a754ea3e1..49137eff0c8e 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -6034,6 +6034,19 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) - return target; - } - -+static unsigned int uclamp_task_util(struct task_struct *p) -+{ -+#ifdef CONFIG_UCLAMP_TASK -+ unsigned int min_util = uclamp_eff_value(p, UCLAMP_MIN); -+ unsigned int max_util = uclamp_eff_value(p, UCLAMP_MAX); -+ unsigned int est_util = task_util_est(p); -+ -+ return clamp(est_util, min_util, max_util); -+#else -+ return task_util_est(p); -+#endif -+} -+ - /** - * Amount of capacity of a CPU that is (estimated to be) used by CFS tasks - * @cpu: the CPU to get the utilization of -@@ -6378,6 +6391,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) - if (!fits_capacity(util, cpu_cap)) - continue; - -+ /* Skip CPUs which do not fit task requirements */ -+ if (cpu_cap < uclamp_task_util(p)) -+ continue; -+ - /* Always use prev_cpu as a candidate. */ - if (cpu == prev_cpu) { - prev_delta = compute_energy(p, prev_cpu, pd); diff --git a/patches/ANDROID-sched-fair-add-arch-scaling-function-for-max-frequency-capping.patch b/patches/ANDROID-sched-fair-add-arch-scaling-function-for-max-frequency-capping.patch deleted file mode 100644 index 79a4b3ac8995c0309044d64830ddc86f3d324412..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sched-fair-add-arch-scaling-function-for-max-frequency-capping.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dietmar Eggemann -Date: Thu, 10 May 2018 15:48:06 +0100 -Subject: ANDROID: sched/fair: add arch scaling function for max frequency - capping - -To be able to scale the cpu capacity by this factor introduce a call to -the new arch scaling function arch_scale_max_freq_capacity() in -update_cpu_capacity() and provide a default implementation which returns -SCHED_CAPACITY_SCALE. - -Another subsystem (e.g. cpufreq) or architectural or platform specific -code can overwrite this default implementation, exactly as for frequency -and cpu invariance. It has to be enabled by the arch by defining -arch_scale_max_freq_capacity to the actual implementation. - -Change-Id: I770a8b1f4f7340e9e314f71c64a765bf880f4b4d -Signed-off-by: Ionela Voinescu -Signed-off-by: Dietmar Eggemann -( Fixed conflict with scaling against the PELT-based scale_rt_capacity ) -Signed-off-by: Quentin Perret ---- - kernel/sched/fair.c | 12 ++++++++---- - kernel/sched/sched.h | 9 +++++++++ - 2 files changed, 17 insertions(+), 4 deletions(-) - -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index 43d3321ce61e..c0b1c1233727 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -7733,10 +7733,9 @@ static inline void init_sd_lb_stats(struct sd_lb_stats *sds) - }; - } - --static unsigned long scale_rt_capacity(struct sched_domain *sd, int cpu) -+static unsigned long scale_rt_capacity(int cpu, unsigned long max) - { - struct rq *rq = cpu_rq(cpu); -- unsigned long max = arch_scale_cpu_capacity(cpu); - unsigned long used, free; - unsigned long irq; - -@@ -7758,10 +7757,15 @@ static unsigned long scale_rt_capacity(struct sched_domain *sd, int cpu) - - static void update_cpu_capacity(struct sched_domain *sd, int cpu) - { -- unsigned long capacity = scale_rt_capacity(sd, cpu); -+ unsigned long capacity = arch_scale_cpu_capacity(cpu); - struct sched_group *sdg = sd->groups; - -- cpu_rq(cpu)->cpu_capacity_orig = arch_scale_cpu_capacity(cpu); -+ cpu_rq(cpu)->cpu_capacity_orig = capacity; -+ -+ capacity *= arch_scale_max_freq_capacity(sd, cpu); -+ capacity >>= SCHED_CAPACITY_SHIFT; -+ -+ capacity = scale_rt_capacity(cpu, capacity); - - if (!capacity) - capacity = 1; -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index 0db2c1b3361e..f0b6e3ab2c96 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -1961,6 +1961,15 @@ unsigned long arch_scale_freq_capacity(int cpu) - } - #endif - -+#ifndef arch_scale_max_freq_capacity -+struct sched_domain; -+static __always_inline -+unsigned long arch_scale_max_freq_capacity(struct sched_domain *sd, int cpu) -+{ -+ return SCHED_CAPACITY_SCALE; -+} -+#endif -+ - #ifdef CONFIG_SMP - #ifdef CONFIG_PREEMPTION - diff --git a/patches/ANDROID-sdcardfs-Add-sdcardfs-filesystem.patch b/patches/ANDROID-sdcardfs-Add-sdcardfs-filesystem.patch deleted file mode 100644 index 81ae7b528ca244e7c9c47e99d732b481da64d41f..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sdcardfs-Add-sdcardfs-filesystem.patch +++ /dev/null @@ -1,5179 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Campello -Date: Mon, 20 Jul 2015 16:23:50 -0700 -Subject: ANDROID: sdcardfs: Add sdcardfs filesystem - -Bug: 11118565 -Bug: 27915347 -Bug: 27992761 -Bug: 28024488 -Bug: 30013843 -Bug: 30954918 -Bug: 34133558 -Bug: 34262585 -Bug: 34542611 -Bug: 34691169 -Bug: 34723223 -Bug: 35307857 -Bug: 35331000 -Bug: 35633782 -Bug: 35643557 -Bug: 35666680 -bug: 35766959 -Bug: 35766959 -Bug: 35848445 -Bug: 36004503 -Bug: 36007653 -Bug: 36138424 -Bug: 36160015 -Bug: 37193650 -Bug: 37231161 -Bug: 37488099 -Bug: 37516160 -Bug: 38045152 -Bug: 38117720 -Bug: 38502532 -Bug: 62390017 -Bug: 63245673 -Bug: 63260873 -Bug: 63785372 -Bug: 64672411 -Bug: 70278506 -Bug: 72007585 -Bug: 73055997 -Bug: 73287721 -Bug: 75987238 -Bug: 77923821 -Bug: 78262592 -Bug: 111641492 -Bug: 111642636 -Bug: 111860541 -Change-Id: Ic1e01e602ce335d97342be54f3da0c5c65c087cc -Signed-off-by: Daniel Rosenberg -[astrachan: Folded the following changes into this patch: - 903cea7ab0b2 ("ANDROID: Included sdcardfs source code for kernel 3.0") - 612a725e3d97 ("ANDROID: Port of sdcardfs to 4.4") - e4187c55208b ("ANDROID: Changed type-casting in packagelist management") - cf76072a5cd8 ("ANDROID: sdcardfs: Bring up to date with Android M permissions:") - a43aa502c608 ("ANDROID: sdcardfs: Add support for d_canonical_path") - d8fefbf85af2 ("ANDROID: sdcardfs: remove effectless config option") - 416677409336 ("ANDROID: sdcardfs: Remove unused code") - 8e49a570d351 ("ANDROID: sdcardfs: remove unneeded __init and __exit") - 40ee0e93f1d7 ("ANDROID: sdcardfs: Truncate packages_gid.list on overflow") - b1d9602aa3fe ("ANDROID: sdcardfs: fix itnull.cocci warnings") - 60a177f5a167 ("ANDROID: sdcardfs: override umask on mkdir and create") - efb3d2695203 ("ANDROID: sdcardfs: Check for other cases on path lookup") - 0da87f63666f ("ANDROID: sdcardfs: Fix locking for permission fix up") - 75b93060655e ("ANDROID: sdcardfs: Switch package list to RCU") - 657b0a00f497 ("ANDROID: sdcardfs: Added top to sdcardfs_inode_info") - 5008d91cba25 ("ANDROID: sdcardfs: fix external storage exporting incorrect uid") - e06c452d0d07 ("ANDROID: sdcardfs: Move directory unlock before touch") - 72e5443a2816 ("ANDROID: sdcardfs: User new permission2 functions") - ae8be7da556d ("ANDROID: sdcardfs: Add gid and mask to private mount data") - 151a3efe57a6 ("ANDROID: sdcardfs: Use per mount permissions") - cff865a370f3 ("ANDROID: sdcardfs: Switch ->d_inode to d_inode()") - 065ac66804bf ("ANDROID: sdcardfs: Fix locking issue with permision fix up") - 31ea603eb3c4 ("ANDROID: sdcardfs: use wrappers to access i_mutex") - c25c2f5018a2 ("ANDROID: sdcardfs: add parent pointer into dentry name hash") - 58616bb4ec68 ("ANDROID: sdcardfs: get rid of 'parent' argument of ->d_compare()") - 1654d7ffdd20 ("ANDROID: sdcardfs: Propagate dentry down to inode_change_ok()") - 39335cac1d2f ("ANDROID: sdcardfs: make it use new .rename i_op") - 7622bb3fcc79 ("ANDROID: sdcardfs: eliminate the offset argument to ->direct_IO") - 843bd7295ee0 ("ANDROID: sdcardfs: Allow non-owners to touch") - e3d74804d174 ("ANDROID: sdcardfs: Refactor configfs interface") - 5833eda87a72 ("ANDROID: sdcardfs: add support for user permission isolation") - d83fb1f41dd4 ("ANDROID: sdcardfs: Remove redundant operation") - 8767af17c0e5 ("ANDROID: sdcardfs: Add GID Derivation to sdcardfs") - 7119d96ad3ee ("ANDROID: sdcardfs: switch to full_name_hash and qstr") - 778e02a54859 ("ANDROID: sdcardfs: Switch strcasecmp for internal call") - cd4965d04404 ("ANDROID: sdcardfs: Fix incorrect hash") - 40a2ee053505 ("ANDROID: sdcardfs: Add missing path_put") - da5342bac57a ("ANDROID: sdcardfs: Don't bother deleting freelist") - c91857b01e05 ("ANDROID: sdcardfs: implement vm_ops->page_mkwrite") - f62b3906044b ("ANDROID: sdcardfs: support direct-IO (DIO) operations") - c2e216d36d63 ("ANDROID: sdcardfs: Fix case insensitive lookup") - 57b92ab6f774 ("ANDROID: sdcardfs: rate limit warning print") - 8534cee39a81 ("ANDROID: sdcardfs: Replace get/put with d_lock") - 156085b2fccf ("ANDROID: sdcardfs: Use spin_lock_nested") - 8a260cabac4e ("ANDROID: sdcardfs: Switch to internal case insensitive compare") - a8d51569573c ("ANDROID: sdcardfs: Use d_invalidate instead of drop_recurisve") - 932a6071de63 ("ANDROID: sdcardfs: Get the blocksize from the lower fs") - 0ad4c0f87527 ("ANDROID: sdcardfs: declare MODULE_ALIAS_FS") - b97c83b5b683 ("ANDROID: sdcardfs: Use case insensitive hash function") - 9920dfb08265 ("ANDROID: sdcardfs: move path_put outside of spinlock") - f9a25348b233 ("ANDROID: sdcardfs: Remove uninformative prints") - 720d9030bea1 ("ANDROID: sdcardfs: Fix gid issue") - 4cbb7fa6e66c ("ANDROID: sdcardfs: correct order of descriptors") - 6cff6cc301ed ("ANDROID: sdcardfs: Fix formatting") - ac2a40412e26 ("ANDROID: sdcardfs: Fix style issues with comments") - 2212bb8ec064 ("ANDROID: sdcardfs: remove unneeded null check") - 4c1a0add8d21 ("ANDROID: sdcardfs: Use pr_[...] instead of printk") - 74535fe211ac ("ANDROID: sdcardfs: Use to kstrout") - e6cf8dffd014 ("ANDROID: sdcardfs: Use seq_puts over seq_printf") - 2b1ac93a90b6 ("ANDROID: sdcardfs: Fix style issues in macros") - bab6d117426f ("ANDROID: sdcardfs: remove unnecessary call to do_munmap") - 1c0bf09f19b6 ("ANDROID: sdcardfs: copy lower inode attributes in ->ioctl") - 42f3db55942b ("ANDROID: sdcardfs: fix ->llseek to update upper and lower offset") - 97ad6205055e ("ANDROID: sdcardfs: add read_iter/write_iter opeations") - be9abc81332b ("ANDROID: sdcardfs: use d_splice_alias") - 4e90114cb1b4 ("ANDROID: sdcardfs: update module info") - 0e1f7ab14924 ("ANDROID: sdcardfs: Directly pass lower file for mmap") - 28be4beb43f9 ("ANDROID: sdcardfs: Change cache GID value") - 9fc2c452aefe ("ANDROID: sdcardfs: ->iget fixes") - 9bb72cf15cbc ("ANDROID: sdcardfs: Don't do d_add for lower fs") - 1bc21a04c11b ("ANDROID: sdcardfs: Don't complain in fixup_lower_ownership") - 0fb5b10b28a9 ("ANDROID: sdcardfs: Use filesystem specific hash") - 30e2f0aadce2 ("ANDROID: sdcardfs: Copy meta-data from lower inode") - f748c7053194 ("ANDROID: sdcardfs: Avoid setting GIDs outside of valid ranges") - 3d38f08bacdb ("ANDROID: sdcardfs: Call lower fs's revalidate") - 2d1f1c203978 ("ANDROID: sdcardfs: Don't iput if we didn't igrab") - 857fc5e717fc ("ANDROID: sdcardfs: fix sdcardfs_destroy_inode for the inode RCU approach") - 4fceeccf1d23 ("ANDROID: sdcardfs: Move top to its own struct") - f51470044a15 ("ANDROID: sdcardfs: Check for NULL in revalidate") - 8c7f6c97ac81 ("ANDROID: sdcardfs: d_splice_alias can return error values") - 17da01b37d61 ("ANDROID: sdcardfs: remove dead function open_flags_to_access_mode()") - 16662dd604be ("ANDROID: sdcardfs: use mount_nodev and fix a issue in sdcardfs_kill_sb") - 43c0dca6039a ("ANDROID: sdcardfs: Remove unnecessary lock") - 48960c25cdc1 ("ANDROID: sdcardfs: override credential for ioctl to lower fs") - 5d6410b9a88d ("ANDROID: Sdcardfs: Move gid derivation under flag") - c7dd98431f83 ("ANDROID: sdcardfs: Add default_normal option") - db9bf31a5d86 ("ANDROID: sdcardfs: port to 4.14") - c70c9d1e82d2 ("ANDROID: sdcardfs: Use lower getattr times/size") - 04e961477d62 ("ANDROID: sdcardfs: Protect set_top") - 1ed04b79d281 ("ANDROID: sdcardfs: Hold i_mutex for i_size_write") - 77f52fc10982 ("ANDROID: sdcardfs: Set num in extension_details during make_item") - d71596efa247 ("ANDROID: sdcardfs: fix lock issue on 32 bit/SMP architectures") - ee6b07fced4a ("ANDROID: sdcardfs: Fix sdcardfs to stop creating cases-sensitive duplicate entries.") - ce12807d5b75 ("ANDROID: sdcardfs: Check for private data earlier") - c080450304cd ("ANDROID: sdcardfs: d_make_root calls iput") - 900e77796781 ("ANDROID: sdcardfs: Set s_root to NULL after putting") - 49092e89ffa4 ("ANDROID: sdcardfs: Don't d_drop in d_revalidate") - e1f978bc9b9c ("ANDROID: sdcardfs: fix potential crash when reserved_mb is not zero") - faa148eaf8ed ("ANDROID: sdcardfs: Check stacked filesystem depth") - 6edd721e972c ("ANDROID: sdcardfs: Don't use OVERRIDE_CRED macro") - 11ca578b4336 ("ANDROID: sdcardfs: Change current->fs under lock") - 83dea6ba6ea7 ("ANDROID: sdcardfs: Use inode iversion helpers") - 12064f3a794e ("ANDROID: sdcardfs: Add option to drop unused dentries") - d9fe221bbf84 ("ANDROID: sdcardfs: Add sandbox") - f544ad0b1547 ("ANDROID: sdcardfs: Add option to not link obb")] -Signed-off-by: Alistair Strachan -[drosen: folded in e6e368c99975 ("fs: sdcardfs: Add missing option to show_options")] ---- - fs/Kconfig | 1 + - fs/Makefile | 1 + - fs/sdcardfs/Kconfig | 13 + - fs/sdcardfs/Makefile | 7 + - fs/sdcardfs/dentry.c | 196 +++++++++ - fs/sdcardfs/derived_perm.c | 477 ++++++++++++++++++++ - fs/sdcardfs/file.c | 467 ++++++++++++++++++++ - fs/sdcardfs/inode.c | 821 ++++++++++++++++++++++++++++++++++ - fs/sdcardfs/lookup.c | 470 ++++++++++++++++++++ - fs/sdcardfs/main.c | 454 +++++++++++++++++++ - fs/sdcardfs/mmap.c | 87 ++++ - fs/sdcardfs/multiuser.h | 53 +++ - fs/sdcardfs/packagelist.c | 882 +++++++++++++++++++++++++++++++++++++ - fs/sdcardfs/sdcardfs.h | 662 ++++++++++++++++++++++++++++ - fs/sdcardfs/super.c | 297 +++++++++++++ - 15 files changed, 4888 insertions(+) - create mode 100644 fs/sdcardfs/Kconfig - create mode 100644 fs/sdcardfs/Makefile - create mode 100644 fs/sdcardfs/dentry.c - create mode 100644 fs/sdcardfs/derived_perm.c - create mode 100644 fs/sdcardfs/file.c - create mode 100644 fs/sdcardfs/inode.c - create mode 100644 fs/sdcardfs/lookup.c - create mode 100644 fs/sdcardfs/main.c - create mode 100644 fs/sdcardfs/mmap.c - create mode 100644 fs/sdcardfs/multiuser.h - create mode 100644 fs/sdcardfs/packagelist.c - create mode 100644 fs/sdcardfs/sdcardfs.h - create mode 100644 fs/sdcardfs/super.c - -diff --git a/fs/Kconfig b/fs/Kconfig -index 2501e6f1f965..42fe99e24071 100644 ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -243,6 +243,7 @@ source "fs/orangefs/Kconfig" - source "fs/adfs/Kconfig" - source "fs/affs/Kconfig" - source "fs/ecryptfs/Kconfig" -+source "fs/sdcardfs/Kconfig" - source "fs/hfs/Kconfig" - source "fs/hfsplus/Kconfig" - source "fs/befs/Kconfig" -diff --git a/fs/Makefile b/fs/Makefile -index 14231b4cf383..cc5524e8acda 100644 ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -87,6 +87,7 @@ obj-$(CONFIG_ISO9660_FS) += isofs/ - obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ - obj-$(CONFIG_HFS_FS) += hfs/ - obj-$(CONFIG_ECRYPT_FS) += ecryptfs/ -+obj-$(CONFIG_SDCARD_FS) += sdcardfs/ - obj-$(CONFIG_VXFS_FS) += freevxfs/ - obj-$(CONFIG_NFS_FS) += nfs/ - obj-$(CONFIG_EXPORTFS) += exportfs/ -diff --git a/fs/sdcardfs/Kconfig b/fs/sdcardfs/Kconfig -new file mode 100644 -index 000000000000..a1c103316ac7 ---- /dev/null -+++ b/fs/sdcardfs/Kconfig -@@ -0,0 +1,13 @@ -+config SDCARD_FS -+ tristate "sdcard file system" -+ depends on CONFIGFS_FS -+ default n -+ help -+ Sdcardfs is based on Wrapfs file system. -+ -+config SDCARD_FS_FADV_NOACTIVE -+ bool "sdcardfs fadvise noactive support" -+ depends on FADV_NOACTIVE -+ default y -+ help -+ Sdcardfs supports fadvise noactive mode. -diff --git a/fs/sdcardfs/Makefile b/fs/sdcardfs/Makefile -new file mode 100644 -index 000000000000..b84fbb2b45a4 ---- /dev/null -+++ b/fs/sdcardfs/Makefile -@@ -0,0 +1,7 @@ -+SDCARDFS_VERSION="0.1" -+ -+EXTRA_CFLAGS += -DSDCARDFS_VERSION=\"$(SDCARDFS_VERSION)\" -+ -+obj-$(CONFIG_SDCARD_FS) += sdcardfs.o -+ -+sdcardfs-y := dentry.o file.o inode.o main.o super.o lookup.o mmap.o packagelist.o derived_perm.o -diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c -new file mode 100644 -index 000000000000..cb573f1efbfc ---- /dev/null -+++ b/fs/sdcardfs/dentry.c -@@ -0,0 +1,196 @@ -+/* -+ * fs/sdcardfs/dentry.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+#include "linux/ctype.h" -+ -+/* -+ * returns: -ERRNO if error (returned to user) -+ * 0: tell VFS to invalidate dentry -+ * 1: dentry is valid -+ */ -+static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) -+{ -+ int err = 1; -+ struct path parent_lower_path, lower_path; -+ struct dentry *parent_dentry = NULL; -+ struct dentry *parent_lower_dentry = NULL; -+ struct dentry *lower_cur_parent_dentry = NULL; -+ struct dentry *lower_dentry = NULL; -+ struct inode *inode; -+ struct sdcardfs_inode_data *data; -+ -+ if (flags & LOOKUP_RCU) -+ return -ECHILD; -+ -+ spin_lock(&dentry->d_lock); -+ if (IS_ROOT(dentry)) { -+ spin_unlock(&dentry->d_lock); -+ return 1; -+ } -+ spin_unlock(&dentry->d_lock); -+ -+ /* check uninitialized obb_dentry and -+ * whether the base obbpath has been changed or not -+ */ -+ if (is_obbpath_invalid(dentry)) { -+ return 0; -+ } -+ -+ parent_dentry = dget_parent(dentry); -+ sdcardfs_get_lower_path(parent_dentry, &parent_lower_path); -+ sdcardfs_get_real_lower(dentry, &lower_path); -+ parent_lower_dentry = parent_lower_path.dentry; -+ lower_dentry = lower_path.dentry; -+ lower_cur_parent_dentry = dget_parent(lower_dentry); -+ -+ if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) { -+ err = lower_dentry->d_op->d_revalidate(lower_dentry, flags); -+ if (err == 0) { -+ goto out; -+ } -+ } -+ -+ spin_lock(&lower_dentry->d_lock); -+ if (d_unhashed(lower_dentry)) { -+ spin_unlock(&lower_dentry->d_lock); -+ err = 0; -+ goto out; -+ } -+ spin_unlock(&lower_dentry->d_lock); -+ -+ if (parent_lower_dentry != lower_cur_parent_dentry) { -+ err = 0; -+ goto out; -+ } -+ -+ if (dentry < lower_dentry) { -+ spin_lock(&dentry->d_lock); -+ spin_lock_nested(&lower_dentry->d_lock, DENTRY_D_LOCK_NESTED); -+ } else { -+ spin_lock(&lower_dentry->d_lock); -+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); -+ } -+ -+ if (!qstr_case_eq(&dentry->d_name, &lower_dentry->d_name)) { -+ err = 0; -+ } -+ -+ if (dentry < lower_dentry) { -+ spin_unlock(&lower_dentry->d_lock); -+ spin_unlock(&dentry->d_lock); -+ } else { -+ spin_unlock(&dentry->d_lock); -+ spin_unlock(&lower_dentry->d_lock); -+ } -+ if (!err) -+ goto out; -+ -+ /* If our top's inode is gone, we may be out of date */ -+ inode = igrab(d_inode(dentry)); -+ if (inode) { -+ data = top_data_get(SDCARDFS_I(inode)); -+ if (!data || data->abandoned) { -+ err = 0; -+ } -+ if (data) -+ data_put(data); -+ iput(inode); -+ } -+ -+out: -+ dput(parent_dentry); -+ dput(lower_cur_parent_dentry); -+ sdcardfs_put_lower_path(parent_dentry, &parent_lower_path); -+ sdcardfs_put_real_lower(dentry, &lower_path); -+ return err; -+} -+ -+/* 1 = delete, 0 = cache */ -+static int sdcardfs_d_delete(const struct dentry *d) -+{ -+ return SDCARDFS_SB(d->d_sb)->options.nocache ? 1 : 0; -+} -+ -+static void sdcardfs_d_release(struct dentry *dentry) -+{ -+ if (!dentry || !dentry->d_fsdata) -+ return; -+ /* release and reset the lower paths */ -+ if (has_graft_path(dentry)) -+ sdcardfs_put_reset_orig_path(dentry); -+ sdcardfs_put_reset_lower_path(dentry); -+ free_dentry_private_data(dentry); -+} -+ -+static int sdcardfs_hash_ci(const struct dentry *dentry, -+ struct qstr *qstr) -+{ -+ /* -+ * This function is copy of vfat_hashi. -+ * FIXME Should we support national language? -+ * Refer to vfat_hashi() -+ * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; -+ */ -+ const unsigned char *name; -+ unsigned int len; -+ unsigned long hash; -+ -+ name = qstr->name; -+ len = qstr->len; -+ -+ hash = init_name_hash(dentry); -+ while (len--) -+ hash = partial_name_hash(tolower(*name++), hash); -+ qstr->hash = end_name_hash(hash); -+ -+ return 0; -+} -+ -+/* -+ * Case insensitive compare of two vfat names. -+ */ -+static int sdcardfs_cmp_ci(const struct dentry *dentry, -+ unsigned int len, const char *str, const struct qstr *name) -+{ -+ /* FIXME Should we support national language? */ -+ -+ if (name->len == len) { -+ if (str_n_case_eq(name->name, str, len)) -+ return 0; -+ } -+ return 1; -+} -+ -+static void sdcardfs_canonical_path(const struct path *path, -+ struct path *actual_path) -+{ -+ sdcardfs_get_real_lower(path->dentry, actual_path); -+} -+ -+const struct dentry_operations sdcardfs_ci_dops = { -+ .d_revalidate = sdcardfs_d_revalidate, -+ .d_delete = sdcardfs_d_delete, -+ .d_release = sdcardfs_d_release, -+ .d_hash = sdcardfs_hash_ci, -+ .d_compare = sdcardfs_cmp_ci, -+ .d_canonical_path = sdcardfs_canonical_path, -+}; -+ -diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c -new file mode 100644 -index 000000000000..78a669c8a4d6 ---- /dev/null -+++ b/fs/sdcardfs/derived_perm.c -@@ -0,0 +1,477 @@ -+/* -+ * fs/sdcardfs/derived_perm.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+ -+/* copy derived state from parent inode */ -+static void inherit_derived_state(struct inode *parent, struct inode *child) -+{ -+ struct sdcardfs_inode_info *pi = SDCARDFS_I(parent); -+ struct sdcardfs_inode_info *ci = SDCARDFS_I(child); -+ -+ ci->data->perm = PERM_INHERIT; -+ ci->data->userid = pi->data->userid; -+ ci->data->d_uid = pi->data->d_uid; -+ ci->data->under_android = pi->data->under_android; -+ ci->data->under_cache = pi->data->under_cache; -+ ci->data->under_obb = pi->data->under_obb; -+} -+ -+/* helper function for derived state */ -+void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid, -+ uid_t uid) -+{ -+ struct sdcardfs_inode_info *info = SDCARDFS_I(inode); -+ -+ info->data->perm = perm; -+ info->data->userid = userid; -+ info->data->d_uid = uid; -+ info->data->under_android = false; -+ info->data->under_cache = false; -+ info->data->under_obb = false; -+} -+ -+/* While renaming, there is a point where we want the path from dentry, -+ * but the name from newdentry -+ */ -+void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, -+ const struct qstr *name) -+{ -+ struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(dentry)); -+ struct sdcardfs_inode_info *parent_info = SDCARDFS_I(d_inode(parent)); -+ struct sdcardfs_inode_data *parent_data = parent_info->data; -+ appid_t appid; -+ unsigned long user_num; -+ int err; -+ struct qstr q_Android = QSTR_LITERAL("Android"); -+ struct qstr q_data = QSTR_LITERAL("data"); -+ struct qstr q_sandbox = QSTR_LITERAL("sandbox"); -+ struct qstr q_obb = QSTR_LITERAL("obb"); -+ struct qstr q_media = QSTR_LITERAL("media"); -+ struct qstr q_cache = QSTR_LITERAL("cache"); -+ -+ /* By default, each inode inherits from its parent. -+ * the properties are maintained on its private fields -+ * because the inode attributes will be modified with that of -+ * its lower inode. -+ * These values are used by our custom permission call instead -+ * of using the inode permissions. -+ */ -+ -+ inherit_derived_state(d_inode(parent), d_inode(dentry)); -+ -+ /* Files don't get special labels */ -+ if (!S_ISDIR(d_inode(dentry)->i_mode)) { -+ set_top(info, parent_info); -+ return; -+ } -+ /* Derive custom permissions based on parent and current node */ -+ switch (parent_data->perm) { -+ case PERM_INHERIT: -+ case PERM_ANDROID_PACKAGE_CACHE: -+ set_top(info, parent_info); -+ break; -+ case PERM_PRE_ROOT: -+ /* Legacy internal layout places users at top level */ -+ info->data->perm = PERM_ROOT; -+ err = kstrtoul(name->name, 10, &user_num); -+ if (err) -+ info->data->userid = 0; -+ else -+ info->data->userid = user_num; -+ break; -+ case PERM_ROOT: -+ /* Assume masked off by default. */ -+ if (qstr_case_eq(name, &q_Android)) { -+ /* App-specific directories inside; let anyone traverse */ -+ info->data->perm = PERM_ANDROID; -+ info->data->under_android = true; -+ } else { -+ set_top(info, parent_info); -+ } -+ break; -+ case PERM_ANDROID: -+ if (qstr_case_eq(name, &q_data)) { -+ /* App-specific directories inside; let anyone traverse */ -+ info->data->perm = PERM_ANDROID_DATA; -+ } else if (qstr_case_eq(name, &q_sandbox)) { -+ /* App-specific directories inside; let anyone traverse */ -+ info->data->perm = PERM_ANDROID_DATA; -+ } else if (qstr_case_eq(name, &q_obb)) { -+ /* App-specific directories inside; let anyone traverse */ -+ info->data->perm = PERM_ANDROID_OBB; -+ info->data->under_obb = true; -+ /* Single OBB directory is always shared */ -+ } else if (qstr_case_eq(name, &q_media)) { -+ /* App-specific directories inside; let anyone traverse */ -+ info->data->perm = PERM_ANDROID_MEDIA; -+ } else { -+ set_top(info, parent_info); -+ } -+ break; -+ case PERM_ANDROID_OBB: -+ case PERM_ANDROID_DATA: -+ case PERM_ANDROID_MEDIA: -+ info->data->perm = PERM_ANDROID_PACKAGE; -+ appid = get_appid(name->name); -+ if (appid != 0 && !is_excluded(name->name, parent_data->userid)) -+ info->data->d_uid = -+ multiuser_get_uid(parent_data->userid, appid); -+ break; -+ case PERM_ANDROID_PACKAGE: -+ if (qstr_case_eq(name, &q_cache)) { -+ info->data->perm = PERM_ANDROID_PACKAGE_CACHE; -+ info->data->under_cache = true; -+ } -+ set_top(info, parent_info); -+ break; -+ } -+} -+ -+void get_derived_permission(struct dentry *parent, struct dentry *dentry) -+{ -+ get_derived_permission_new(parent, dentry, &dentry->d_name); -+} -+ -+static appid_t get_type(const char *name) -+{ -+ const char *ext = strrchr(name, '.'); -+ appid_t id; -+ -+ if (ext && ext[0]) { -+ ext = &ext[1]; -+ id = get_ext_gid(ext); -+ return id?:AID_MEDIA_RW; -+ } -+ return AID_MEDIA_RW; -+} -+ -+void fixup_lower_ownership(struct dentry *dentry, const char *name) -+{ -+ struct path path; -+ struct inode *inode; -+ struct inode *delegated_inode = NULL; -+ int error; -+ struct sdcardfs_inode_info *info; -+ struct sdcardfs_inode_data *info_d; -+ struct sdcardfs_inode_data *info_top; -+ perm_t perm; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ uid_t uid = sbi->options.fs_low_uid; -+ gid_t gid = sbi->options.fs_low_gid; -+ struct iattr newattrs; -+ -+ if (!sbi->options.gid_derivation) -+ return; -+ -+ info = SDCARDFS_I(d_inode(dentry)); -+ info_d = info->data; -+ perm = info_d->perm; -+ if (info_d->under_obb) { -+ perm = PERM_ANDROID_OBB; -+ } else if (info_d->under_cache) { -+ perm = PERM_ANDROID_PACKAGE_CACHE; -+ } else if (perm == PERM_INHERIT) { -+ info_top = top_data_get(info); -+ perm = info_top->perm; -+ data_put(info_top); -+ } -+ -+ switch (perm) { -+ case PERM_ROOT: -+ case PERM_ANDROID: -+ case PERM_ANDROID_DATA: -+ case PERM_ANDROID_MEDIA: -+ case PERM_ANDROID_PACKAGE: -+ case PERM_ANDROID_PACKAGE_CACHE: -+ uid = multiuser_get_uid(info_d->userid, uid); -+ break; -+ case PERM_ANDROID_OBB: -+ uid = AID_MEDIA_OBB; -+ break; -+ case PERM_PRE_ROOT: -+ default: -+ break; -+ } -+ switch (perm) { -+ case PERM_ROOT: -+ case PERM_ANDROID: -+ case PERM_ANDROID_DATA: -+ case PERM_ANDROID_MEDIA: -+ if (S_ISDIR(d_inode(dentry)->i_mode)) -+ gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW); -+ else -+ gid = multiuser_get_uid(info_d->userid, get_type(name)); -+ break; -+ case PERM_ANDROID_OBB: -+ gid = AID_MEDIA_OBB; -+ break; -+ case PERM_ANDROID_PACKAGE: -+ if (uid_is_app(info_d->d_uid)) -+ gid = multiuser_get_ext_gid(info_d->d_uid); -+ else -+ gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW); -+ break; -+ case PERM_ANDROID_PACKAGE_CACHE: -+ if (uid_is_app(info_d->d_uid)) -+ gid = multiuser_get_ext_cache_gid(info_d->d_uid); -+ else -+ gid = multiuser_get_uid(info_d->userid, AID_MEDIA_RW); -+ break; -+ case PERM_PRE_ROOT: -+ default: -+ break; -+ } -+ -+ sdcardfs_get_lower_path(dentry, &path); -+ inode = d_inode(path.dentry); -+ if (d_inode(path.dentry)->i_gid.val != gid || d_inode(path.dentry)->i_uid.val != uid) { -+retry_deleg: -+ newattrs.ia_valid = ATTR_GID | ATTR_UID | ATTR_FORCE; -+ newattrs.ia_uid = make_kuid(current_user_ns(), uid); -+ newattrs.ia_gid = make_kgid(current_user_ns(), gid); -+ if (!S_ISDIR(inode->i_mode)) -+ newattrs.ia_valid |= -+ ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; -+ inode_lock(inode); -+ error = security_path_chown(&path, newattrs.ia_uid, newattrs.ia_gid); -+ if (!error) -+ error = notify_change2(path.mnt, path.dentry, &newattrs, &delegated_inode); -+ inode_unlock(inode); -+ if (delegated_inode) { -+ error = break_deleg_wait(&delegated_inode); -+ if (!error) -+ goto retry_deleg; -+ } -+ if (error) -+ pr_debug("sdcardfs: Failed to touch up lower fs gid/uid for %s\n", name); -+ } -+ sdcardfs_put_lower_path(dentry, &path); -+} -+ -+static int descendant_may_need_fixup(struct sdcardfs_inode_data *data, -+ struct limit_search *limit) -+{ -+ if (data->perm == PERM_ROOT) -+ return (limit->flags & BY_USERID) ? -+ data->userid == limit->userid : 1; -+ if (data->perm == PERM_PRE_ROOT || data->perm == PERM_ANDROID) -+ return 1; -+ return 0; -+} -+ -+static int needs_fixup(perm_t perm) -+{ -+ if (perm == PERM_ANDROID_DATA || perm == PERM_ANDROID_OBB -+ || perm == PERM_ANDROID_MEDIA) -+ return 1; -+ return 0; -+} -+ -+static void __fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit, int depth) -+{ -+ struct dentry *child; -+ struct sdcardfs_inode_info *info; -+ -+ /* -+ * All paths will terminate their recursion on hitting PERM_ANDROID_OBB, -+ * PERM_ANDROID_MEDIA, or PERM_ANDROID_DATA. This happens at a depth of -+ * at most 3. -+ */ -+ WARN(depth > 3, "%s: Max expected depth exceeded!\n", __func__); -+ spin_lock_nested(&dentry->d_lock, depth); -+ if (!d_inode(dentry)) { -+ spin_unlock(&dentry->d_lock); -+ return; -+ } -+ info = SDCARDFS_I(d_inode(dentry)); -+ -+ if (needs_fixup(info->data->perm)) { -+ list_for_each_entry(child, &dentry->d_subdirs, d_child) { -+ spin_lock_nested(&child->d_lock, depth + 1); -+ if (!(limit->flags & BY_NAME) || qstr_case_eq(&child->d_name, &limit->name)) { -+ if (d_inode(child)) { -+ get_derived_permission(dentry, child); -+ fixup_tmp_permissions(d_inode(child)); -+ spin_unlock(&child->d_lock); -+ break; -+ } -+ } -+ spin_unlock(&child->d_lock); -+ } -+ } else if (descendant_may_need_fixup(info->data, limit)) { -+ list_for_each_entry(child, &dentry->d_subdirs, d_child) { -+ __fixup_perms_recursive(child, limit, depth + 1); -+ } -+ } -+ spin_unlock(&dentry->d_lock); -+} -+ -+void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit) -+{ -+ __fixup_perms_recursive(dentry, limit, 0); -+} -+ -+/* main function for updating derived permission */ -+inline void update_derived_permission_lock(struct dentry *dentry) -+{ -+ struct dentry *parent; -+ -+ if (!dentry || !d_inode(dentry)) { -+ pr_err("sdcardfs: %s: invalid dentry\n", __func__); -+ return; -+ } -+ /* FIXME: -+ * 1. need to check whether the dentry is updated or not -+ * 2. remove the root dentry update -+ */ -+ if (!IS_ROOT(dentry)) { -+ parent = dget_parent(dentry); -+ if (parent) { -+ get_derived_permission(parent, dentry); -+ dput(parent); -+ } -+ } -+ fixup_tmp_permissions(d_inode(dentry)); -+} -+ -+int need_graft_path(struct dentry *dentry) -+{ -+ int ret = 0; -+ struct dentry *parent = dget_parent(dentry); -+ struct sdcardfs_inode_info *parent_info = SDCARDFS_I(d_inode(parent)); -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ struct qstr obb = QSTR_LITERAL("obb"); -+ -+ if (!sbi->options.unshared_obb && -+ parent_info->data->perm == PERM_ANDROID && -+ qstr_case_eq(&dentry->d_name, &obb)) { -+ -+ /* /Android/obb is the base obbpath of DERIVED_UNIFIED */ -+ if (!(sbi->options.multiuser == false -+ && parent_info->data->userid == 0)) { -+ ret = 1; -+ } -+ } -+ dput(parent); -+ return ret; -+} -+ -+int is_obbpath_invalid(struct dentry *dent) -+{ -+ int ret = 0; -+ struct sdcardfs_dentry_info *di = SDCARDFS_D(dent); -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dent->d_sb); -+ char *path_buf, *obbpath_s; -+ int need_put = 0; -+ struct path lower_path; -+ -+ /* check the base obbpath has been changed. -+ * this routine can check an uninitialized obb dentry as well. -+ * regarding the uninitialized obb, refer to the sdcardfs_mkdir() -+ */ -+ spin_lock(&di->lock); -+ if (di->orig_path.dentry) { -+ if (!di->lower_path.dentry) { -+ ret = 1; -+ } else { -+ path_get(&di->lower_path); -+ -+ path_buf = kmalloc(PATH_MAX, GFP_ATOMIC); -+ if (!path_buf) { -+ ret = 1; -+ pr_err("sdcardfs: fail to allocate path_buf in %s.\n", __func__); -+ } else { -+ obbpath_s = d_path(&di->lower_path, path_buf, PATH_MAX); -+ if (d_unhashed(di->lower_path.dentry) || -+ !str_case_eq(sbi->obbpath_s, obbpath_s)) { -+ ret = 1; -+ } -+ kfree(path_buf); -+ } -+ -+ pathcpy(&lower_path, &di->lower_path); -+ need_put = 1; -+ } -+ } -+ spin_unlock(&di->lock); -+ if (need_put) -+ path_put(&lower_path); -+ return ret; -+} -+ -+int is_base_obbpath(struct dentry *dentry) -+{ -+ int ret = 0; -+ struct dentry *parent = dget_parent(dentry); -+ struct sdcardfs_inode_info *parent_info = SDCARDFS_I(d_inode(parent)); -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ struct qstr q_obb = QSTR_LITERAL("obb"); -+ -+ spin_lock(&SDCARDFS_D(dentry)->lock); -+ if (sbi->options.multiuser) { -+ if (parent_info->data->perm == PERM_PRE_ROOT && -+ qstr_case_eq(&dentry->d_name, &q_obb)) { -+ ret = 1; -+ } -+ } else if (parent_info->data->perm == PERM_ANDROID && -+ qstr_case_eq(&dentry->d_name, &q_obb)) { -+ ret = 1; -+ } -+ spin_unlock(&SDCARDFS_D(dentry)->lock); -+ return ret; -+} -+ -+/* The lower_path will be stored to the dentry's orig_path -+ * and the base obbpath will be copyed to the lower_path variable. -+ * if an error returned, there's no change in the lower_path -+ * returns: -ERRNO if error (0: no error) -+ */ -+int setup_obb_dentry(struct dentry *dentry, struct path *lower_path) -+{ -+ int err = 0; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ struct path obbpath; -+ -+ /* A local obb dentry must have its own orig_path to support rmdir -+ * and mkdir of itself. Usually, we expect that the sbi->obbpath -+ * is avaiable on this stage. -+ */ -+ sdcardfs_set_orig_path(dentry, lower_path); -+ -+ err = kern_path(sbi->obbpath_s, -+ LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath); -+ -+ if (!err) { -+ /* the obbpath base has been found */ -+ pathcpy(lower_path, &obbpath); -+ } else { -+ /* if the sbi->obbpath is not available, we can optionally -+ * setup the lower_path with its orig_path. -+ * but, the current implementation just returns an error -+ * because the sdcard daemon also regards this case as -+ * a lookup fail. -+ */ -+ pr_info("sdcardfs: the sbi->obbpath is not available\n"); -+ } -+ return err; -+} -+ -+ -diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c -new file mode 100644 -index 000000000000..271c4c4cb760 ---- /dev/null -+++ b/fs/sdcardfs/file.c -@@ -0,0 +1,467 @@ -+/* -+ * fs/sdcardfs/file.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE -+#include -+#endif -+ -+static ssize_t sdcardfs_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ int err; -+ struct file *lower_file; -+ struct dentry *dentry = file->f_path.dentry; -+#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE -+ struct backing_dev_info *bdi; -+#endif -+ -+ lower_file = sdcardfs_lower_file(file); -+ -+#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE -+ if (file->f_mode & FMODE_NOACTIVE) { -+ if (!(lower_file->f_mode & FMODE_NOACTIVE)) { -+ bdi = lower_file->f_mapping->backing_dev_info; -+ lower_file->f_ra.ra_pages = bdi->ra_pages * 2; -+ spin_lock(&lower_file->f_lock); -+ lower_file->f_mode |= FMODE_NOACTIVE; -+ spin_unlock(&lower_file->f_lock); -+ } -+ } -+#endif -+ -+ err = vfs_read(lower_file, buf, count, ppos); -+ /* update our inode atime upon a successful lower read */ -+ if (err >= 0) -+ fsstack_copy_attr_atime(d_inode(dentry), -+ file_inode(lower_file)); -+ -+ return err; -+} -+ -+static ssize_t sdcardfs_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ int err; -+ struct file *lower_file; -+ struct dentry *dentry = file->f_path.dentry; -+ struct inode *inode = d_inode(dentry); -+ -+ /* check disk space */ -+ if (!check_min_free_space(dentry, count, 0)) { -+ pr_err("No minimum free space.\n"); -+ return -ENOSPC; -+ } -+ -+ lower_file = sdcardfs_lower_file(file); -+ err = vfs_write(lower_file, buf, count, ppos); -+ /* update our inode times+sizes upon a successful lower write */ -+ if (err >= 0) { -+ if (sizeof(loff_t) > sizeof(long)) -+ inode_lock(inode); -+ fsstack_copy_inode_size(inode, file_inode(lower_file)); -+ fsstack_copy_attr_times(inode, file_inode(lower_file)); -+ if (sizeof(loff_t) > sizeof(long)) -+ inode_unlock(inode); -+ } -+ -+ return err; -+} -+ -+static int sdcardfs_readdir(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ struct file *lower_file = NULL; -+ struct dentry *dentry = file->f_path.dentry; -+ -+ lower_file = sdcardfs_lower_file(file); -+ -+ lower_file->f_pos = file->f_pos; -+ err = iterate_dir(lower_file, ctx); -+ file->f_pos = lower_file->f_pos; -+ if (err >= 0) /* copy the atime */ -+ fsstack_copy_attr_atime(d_inode(dentry), -+ file_inode(lower_file)); -+ return err; -+} -+ -+static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ long err = -ENOTTY; -+ struct file *lower_file; -+ const struct cred *saved_cred = NULL; -+ struct dentry *dentry = file->f_path.dentry; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ -+ lower_file = sdcardfs_lower_file(file); -+ -+ /* XXX: use vfs_ioctl if/when VFS exports it */ -+ if (!lower_file || !lower_file->f_op) -+ goto out; -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data); -+ if (!saved_cred) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ if (lower_file->f_op->unlocked_ioctl) -+ err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); -+ -+ /* some ioctls can change inode attributes (EXT2_IOC_SETFLAGS) */ -+ if (!err) -+ sdcardfs_copy_and_fix_attrs(file_inode(file), -+ file_inode(lower_file)); -+ revert_fsids(saved_cred); -+out: -+ return err; -+} -+ -+#ifdef CONFIG_COMPAT -+static long sdcardfs_compat_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ long err = -ENOTTY; -+ struct file *lower_file; -+ const struct cred *saved_cred = NULL; -+ struct dentry *dentry = file->f_path.dentry; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ -+ lower_file = sdcardfs_lower_file(file); -+ -+ /* XXX: use vfs_ioctl if/when VFS exports it */ -+ if (!lower_file || !lower_file->f_op) -+ goto out; -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(sbi, SDCARDFS_I(file_inode(file))->data); -+ if (!saved_cred) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ if (lower_file->f_op->compat_ioctl) -+ err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); -+ -+ revert_fsids(saved_cred); -+out: -+ return err; -+} -+#endif -+ -+static int sdcardfs_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int err = 0; -+ bool willwrite; -+ struct file *lower_file; -+ const struct vm_operations_struct *saved_vm_ops = NULL; -+ -+ /* this might be deferred to mmap's writepage */ -+ willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags); -+ -+ /* -+ * File systems which do not implement ->writepage may use -+ * generic_file_readonly_mmap as their ->mmap op. If you call -+ * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL. -+ * But we cannot call the lower ->mmap op, so we can't tell that -+ * writeable mappings won't work. Therefore, our only choice is to -+ * check if the lower file system supports the ->writepage, and if -+ * not, return EINVAL (the same error that -+ * generic_file_readonly_mmap returns in that case). -+ */ -+ lower_file = sdcardfs_lower_file(file); -+ if (willwrite && !lower_file->f_mapping->a_ops->writepage) { -+ err = -EINVAL; -+ pr_err("sdcardfs: lower file system does not support writeable mmap\n"); -+ goto out; -+ } -+ -+ /* -+ * find and save lower vm_ops. -+ * -+ * XXX: the VFS should have a cleaner way of finding the lower vm_ops -+ */ -+ if (!SDCARDFS_F(file)->lower_vm_ops) { -+ err = lower_file->f_op->mmap(lower_file, vma); -+ if (err) { -+ pr_err("sdcardfs: lower mmap failed %d\n", err); -+ goto out; -+ } -+ saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */ -+ } -+ -+ /* -+ * Next 3 lines are all I need from generic_file_mmap. I definitely -+ * don't want its test for ->readpage which returns -ENOEXEC. -+ */ -+ file_accessed(file); -+ vma->vm_ops = &sdcardfs_vm_ops; -+ -+ file->f_mapping->a_ops = &sdcardfs_aops; /* set our aops */ -+ if (!SDCARDFS_F(file)->lower_vm_ops) /* save for our ->fault */ -+ SDCARDFS_F(file)->lower_vm_ops = saved_vm_ops; -+ vma->vm_private_data = file; -+ get_file(lower_file); -+ vma->vm_file = lower_file; -+ -+out: -+ return err; -+} -+ -+static int sdcardfs_open(struct inode *inode, struct file *file) -+{ -+ int err = 0; -+ struct file *lower_file = NULL; -+ struct path lower_path; -+ struct dentry *dentry = file->f_path.dentry; -+ struct dentry *parent = dget_parent(dentry); -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ const struct cred *saved_cred = NULL; -+ -+ /* don't open unhashed/deleted files */ -+ if (d_unhashed(dentry)) { -+ err = -ENOENT; -+ goto out_err; -+ } -+ -+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) { -+ err = -EACCES; -+ goto out_err; -+ } -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(sbi, SDCARDFS_I(inode)->data); -+ if (!saved_cred) { -+ err = -ENOMEM; -+ goto out_err; -+ } -+ -+ file->private_data = -+ kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); -+ if (!SDCARDFS_F(file)) { -+ err = -ENOMEM; -+ goto out_revert_cred; -+ } -+ -+ /* open lower object and link sdcardfs's file struct to lower's */ -+ sdcardfs_get_lower_path(file->f_path.dentry, &lower_path); -+ lower_file = dentry_open(&lower_path, file->f_flags, current_cred()); -+ path_put(&lower_path); -+ if (IS_ERR(lower_file)) { -+ err = PTR_ERR(lower_file); -+ lower_file = sdcardfs_lower_file(file); -+ if (lower_file) { -+ sdcardfs_set_lower_file(file, NULL); -+ fput(lower_file); /* fput calls dput for lower_dentry */ -+ } -+ } else { -+ sdcardfs_set_lower_file(file, lower_file); -+ } -+ -+ if (err) -+ kfree(SDCARDFS_F(file)); -+ else -+ sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode)); -+ -+out_revert_cred: -+ revert_fsids(saved_cred); -+out_err: -+ dput(parent); -+ return err; -+} -+ -+static int sdcardfs_flush(struct file *file, fl_owner_t id) -+{ -+ int err = 0; -+ struct file *lower_file = NULL; -+ -+ lower_file = sdcardfs_lower_file(file); -+ if (lower_file && lower_file->f_op && lower_file->f_op->flush) { -+ filemap_write_and_wait(file->f_mapping); -+ err = lower_file->f_op->flush(lower_file, id); -+ } -+ -+ return err; -+} -+ -+/* release all lower object references & free the file info structure */ -+static int sdcardfs_file_release(struct inode *inode, struct file *file) -+{ -+ struct file *lower_file; -+ -+ lower_file = sdcardfs_lower_file(file); -+ if (lower_file) { -+ sdcardfs_set_lower_file(file, NULL); -+ fput(lower_file); -+ } -+ -+ kfree(SDCARDFS_F(file)); -+ return 0; -+} -+ -+static int sdcardfs_fsync(struct file *file, loff_t start, loff_t end, -+ int datasync) -+{ -+ int err; -+ struct file *lower_file; -+ struct path lower_path; -+ struct dentry *dentry = file->f_path.dentry; -+ -+ err = __generic_file_fsync(file, start, end, datasync); -+ if (err) -+ goto out; -+ -+ lower_file = sdcardfs_lower_file(file); -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ err = vfs_fsync_range(lower_file, start, end, datasync); -+ sdcardfs_put_lower_path(dentry, &lower_path); -+out: -+ return err; -+} -+ -+static int sdcardfs_fasync(int fd, struct file *file, int flag) -+{ -+ int err = 0; -+ struct file *lower_file = NULL; -+ -+ lower_file = sdcardfs_lower_file(file); -+ if (lower_file->f_op && lower_file->f_op->fasync) -+ err = lower_file->f_op->fasync(fd, lower_file, flag); -+ -+ return err; -+} -+ -+/* -+ * Sdcardfs cannot use generic_file_llseek as ->llseek, because it would -+ * only set the offset of the upper file. So we have to implement our -+ * own method to set both the upper and lower file offsets -+ * consistently. -+ */ -+static loff_t sdcardfs_file_llseek(struct file *file, loff_t offset, int whence) -+{ -+ int err; -+ struct file *lower_file; -+ -+ err = generic_file_llseek(file, offset, whence); -+ if (err < 0) -+ goto out; -+ -+ lower_file = sdcardfs_lower_file(file); -+ err = generic_file_llseek(lower_file, offset, whence); -+ -+out: -+ return err; -+} -+ -+/* -+ * Sdcardfs read_iter, redirect modified iocb to lower read_iter -+ */ -+ssize_t sdcardfs_read_iter(struct kiocb *iocb, struct iov_iter *iter) -+{ -+ int err; -+ struct file *file = iocb->ki_filp, *lower_file; -+ -+ lower_file = sdcardfs_lower_file(file); -+ if (!lower_file->f_op->read_iter) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ get_file(lower_file); /* prevent lower_file from being released */ -+ iocb->ki_filp = lower_file; -+ err = lower_file->f_op->read_iter(iocb, iter); -+ iocb->ki_filp = file; -+ fput(lower_file); -+ /* update upper inode atime as needed */ -+ if (err >= 0 || err == -EIOCBQUEUED) -+ fsstack_copy_attr_atime(file->f_path.dentry->d_inode, -+ file_inode(lower_file)); -+out: -+ return err; -+} -+ -+/* -+ * Sdcardfs write_iter, redirect modified iocb to lower write_iter -+ */ -+ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter) -+{ -+ int err; -+ struct file *file = iocb->ki_filp, *lower_file; -+ struct inode *inode = file->f_path.dentry->d_inode; -+ -+ lower_file = sdcardfs_lower_file(file); -+ if (!lower_file->f_op->write_iter) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ get_file(lower_file); /* prevent lower_file from being released */ -+ iocb->ki_filp = lower_file; -+ err = lower_file->f_op->write_iter(iocb, iter); -+ iocb->ki_filp = file; -+ fput(lower_file); -+ /* update upper inode times/sizes as needed */ -+ if (err >= 0 || err == -EIOCBQUEUED) { -+ if (sizeof(loff_t) > sizeof(long)) -+ inode_lock(inode); -+ fsstack_copy_inode_size(inode, file_inode(lower_file)); -+ fsstack_copy_attr_times(inode, file_inode(lower_file)); -+ if (sizeof(loff_t) > sizeof(long)) -+ inode_unlock(inode); -+ } -+out: -+ return err; -+} -+ -+const struct file_operations sdcardfs_main_fops = { -+ .llseek = generic_file_llseek, -+ .read = sdcardfs_read, -+ .write = sdcardfs_write, -+ .unlocked_ioctl = sdcardfs_unlocked_ioctl, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = sdcardfs_compat_ioctl, -+#endif -+ .mmap = sdcardfs_mmap, -+ .open = sdcardfs_open, -+ .flush = sdcardfs_flush, -+ .release = sdcardfs_file_release, -+ .fsync = sdcardfs_fsync, -+ .fasync = sdcardfs_fasync, -+ .read_iter = sdcardfs_read_iter, -+ .write_iter = sdcardfs_write_iter, -+}; -+ -+/* trimmed directory options */ -+const struct file_operations sdcardfs_dir_fops = { -+ .llseek = sdcardfs_file_llseek, -+ .read = generic_read_dir, -+ .iterate = sdcardfs_readdir, -+ .unlocked_ioctl = sdcardfs_unlocked_ioctl, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = sdcardfs_compat_ioctl, -+#endif -+ .open = sdcardfs_open, -+ .release = sdcardfs_file_release, -+ .flush = sdcardfs_flush, -+ .fsync = sdcardfs_fsync, -+ .fasync = sdcardfs_fasync, -+}; -diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c -new file mode 100644 -index 000000000000..4dd681e0d59d ---- /dev/null -+++ b/fs/sdcardfs/inode.c -@@ -0,0 +1,821 @@ -+/* -+ * fs/sdcardfs/inode.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+#include -+#include -+#include -+ -+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, -+ struct sdcardfs_inode_data *data) -+{ -+ struct cred *cred; -+ const struct cred *old_cred; -+ uid_t uid; -+ -+ cred = prepare_creds(); -+ if (!cred) -+ return NULL; -+ -+ if (sbi->options.gid_derivation) { -+ if (data->under_obb) -+ uid = AID_MEDIA_OBB; -+ else -+ uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid); -+ } else { -+ uid = sbi->options.fs_low_uid; -+ } -+ cred->fsuid = make_kuid(&init_user_ns, uid); -+ cred->fsgid = make_kgid(&init_user_ns, sbi->options.fs_low_gid); -+ -+ old_cred = override_creds(cred); -+ -+ return old_cred; -+} -+ -+void revert_fsids(const struct cred *old_cred) -+{ -+ const struct cred *cur_cred; -+ -+ cur_cred = current->cred; -+ revert_creds(old_cred); -+ put_cred(cur_cred); -+} -+ -+static int sdcardfs_create(struct inode *dir, struct dentry *dentry, -+ umode_t mode, bool want_excl) -+{ -+ int err; -+ struct dentry *lower_dentry; -+ struct vfsmount *lower_dentry_mnt; -+ struct dentry *lower_parent_dentry = NULL; -+ struct path lower_path; -+ const struct cred *saved_cred = NULL; -+ struct fs_struct *saved_fs; -+ struct fs_struct *copied_fs; -+ -+ if (!check_caller_access_to_name(dir, &dentry->d_name)) { -+ err = -EACCES; -+ goto out_eacces; -+ } -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), -+ SDCARDFS_I(dir)->data); -+ if (!saved_cred) -+ return -ENOMEM; -+ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ lower_dentry = lower_path.dentry; -+ lower_dentry_mnt = lower_path.mnt; -+ lower_parent_dentry = lock_parent(lower_dentry); -+ -+ /* set last 16bytes of mode field to 0664 */ -+ mode = (mode & S_IFMT) | 00664; -+ -+ /* temporarily change umask for lower fs write */ -+ saved_fs = current->fs; -+ copied_fs = copy_fs_struct(current->fs); -+ if (!copied_fs) { -+ err = -ENOMEM; -+ goto out_unlock; -+ } -+ copied_fs->umask = 0; -+ task_lock(current); -+ current->fs = copied_fs; -+ task_unlock(current); -+ -+ err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); -+ if (err) -+ goto out; -+ -+ err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, -+ SDCARDFS_I(dir)->data->userid); -+ if (err) -+ goto out; -+ fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); -+ fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); -+ fixup_lower_ownership(dentry, dentry->d_name.name); -+ -+out: -+ task_lock(current); -+ current->fs = saved_fs; -+ task_unlock(current); -+ free_fs_struct(copied_fs); -+out_unlock: -+ unlock_dir(lower_parent_dentry); -+ sdcardfs_put_lower_path(dentry, &lower_path); -+ revert_fsids(saved_cred); -+out_eacces: -+ return err; -+} -+ -+static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) -+{ -+ int err; -+ struct dentry *lower_dentry; -+ struct vfsmount *lower_mnt; -+ struct inode *lower_dir_inode = sdcardfs_lower_inode(dir); -+ struct dentry *lower_dir_dentry; -+ struct path lower_path; -+ const struct cred *saved_cred = NULL; -+ -+ if (!check_caller_access_to_name(dir, &dentry->d_name)) { -+ err = -EACCES; -+ goto out_eacces; -+ } -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), -+ SDCARDFS_I(dir)->data); -+ if (!saved_cred) -+ return -ENOMEM; -+ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ lower_dentry = lower_path.dentry; -+ lower_mnt = lower_path.mnt; -+ dget(lower_dentry); -+ lower_dir_dentry = lock_parent(lower_dentry); -+ -+ err = vfs_unlink2(lower_mnt, lower_dir_inode, lower_dentry, NULL); -+ -+ /* -+ * Note: unlinking on top of NFS can cause silly-renamed files. -+ * Trying to delete such files results in EBUSY from NFS -+ * below. Silly-renamed files will get deleted by NFS later on, so -+ * we just need to detect them here and treat such EBUSY errors as -+ * if the upper file was successfully deleted. -+ */ -+ if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) -+ err = 0; -+ if (err) -+ goto out; -+ fsstack_copy_attr_times(dir, lower_dir_inode); -+ fsstack_copy_inode_size(dir, lower_dir_inode); -+ set_nlink(d_inode(dentry), -+ sdcardfs_lower_inode(d_inode(dentry))->i_nlink); -+ d_inode(dentry)->i_ctime = dir->i_ctime; -+ d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */ -+out: -+ unlock_dir(lower_dir_dentry); -+ dput(lower_dentry); -+ sdcardfs_put_lower_path(dentry, &lower_path); -+ revert_fsids(saved_cred); -+out_eacces: -+ return err; -+} -+ -+static int touch(char *abs_path, mode_t mode) -+{ -+ struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode); -+ -+ if (IS_ERR(filp)) { -+ if (PTR_ERR(filp) == -EEXIST) { -+ return 0; -+ } else { -+ pr_err("sdcardfs: failed to open(%s): %ld\n", -+ abs_path, PTR_ERR(filp)); -+ return PTR_ERR(filp); -+ } -+ } -+ filp_close(filp, current->files); -+ return 0; -+} -+ -+static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ int err; -+ int make_nomedia_in_obb = 0; -+ struct dentry *lower_dentry; -+ struct vfsmount *lower_mnt; -+ struct dentry *lower_parent_dentry = NULL; -+ struct dentry *parent_dentry = NULL; -+ struct path lower_path; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ const struct cred *saved_cred = NULL; -+ struct sdcardfs_inode_data *pd = SDCARDFS_I(dir)->data; -+ int touch_err = 0; -+ struct fs_struct *saved_fs; -+ struct fs_struct *copied_fs; -+ struct qstr q_obb = QSTR_LITERAL("obb"); -+ struct qstr q_data = QSTR_LITERAL("data"); -+ -+ if (!check_caller_access_to_name(dir, &dentry->d_name)) { -+ err = -EACCES; -+ goto out_eacces; -+ } -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), -+ SDCARDFS_I(dir)->data); -+ if (!saved_cred) -+ return -ENOMEM; -+ -+ /* check disk space */ -+ parent_dentry = dget_parent(dentry); -+ if (!check_min_free_space(parent_dentry, 0, 1)) { -+ pr_err("sdcardfs: No minimum free space.\n"); -+ err = -ENOSPC; -+ dput(parent_dentry); -+ goto out_revert; -+ } -+ dput(parent_dentry); -+ -+ /* the lower_dentry is negative here */ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ lower_dentry = lower_path.dentry; -+ lower_mnt = lower_path.mnt; -+ lower_parent_dentry = lock_parent(lower_dentry); -+ -+ /* set last 16bytes of mode field to 0775 */ -+ mode = (mode & S_IFMT) | 00775; -+ -+ /* temporarily change umask for lower fs write */ -+ saved_fs = current->fs; -+ copied_fs = copy_fs_struct(current->fs); -+ if (!copied_fs) { -+ err = -ENOMEM; -+ unlock_dir(lower_parent_dentry); -+ goto out_unlock; -+ } -+ copied_fs->umask = 0; -+ task_lock(current); -+ current->fs = copied_fs; -+ task_unlock(current); -+ -+ err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); -+ -+ if (err) { -+ unlock_dir(lower_parent_dentry); -+ goto out; -+ } -+ -+ /* if it is a local obb dentry, setup it with the base obbpath */ -+ if (need_graft_path(dentry)) { -+ -+ err = setup_obb_dentry(dentry, &lower_path); -+ if (err) { -+ /* if the sbi->obbpath is not available, the lower_path won't be -+ * changed by setup_obb_dentry() but the lower path is saved to -+ * its orig_path. this dentry will be revalidated later. -+ * but now, the lower_path should be NULL -+ */ -+ sdcardfs_put_reset_lower_path(dentry); -+ -+ /* the newly created lower path which saved to its orig_path or -+ * the lower_path is the base obbpath. -+ * therefore, an additional path_get is required -+ */ -+ path_get(&lower_path); -+ } else -+ make_nomedia_in_obb = 1; -+ } -+ -+ err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pd->userid); -+ if (err) { -+ unlock_dir(lower_parent_dentry); -+ goto out; -+ } -+ -+ fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir)); -+ fsstack_copy_inode_size(dir, d_inode(lower_parent_dentry)); -+ /* update number of links on parent directory */ -+ set_nlink(dir, sdcardfs_lower_inode(dir)->i_nlink); -+ fixup_lower_ownership(dentry, dentry->d_name.name); -+ unlock_dir(lower_parent_dentry); -+ if ((!sbi->options.multiuser) && (qstr_case_eq(&dentry->d_name, &q_obb)) -+ && (pd->perm == PERM_ANDROID) && (pd->userid == 0)) -+ make_nomedia_in_obb = 1; -+ -+ /* When creating /Android/data and /Android/obb, mark them as .nomedia */ -+ if (make_nomedia_in_obb || -+ ((pd->perm == PERM_ANDROID) -+ && (qstr_case_eq(&dentry->d_name, &q_data)))) { -+ revert_fsids(saved_cred); -+ saved_cred = override_fsids(sbi, -+ SDCARDFS_I(d_inode(dentry))->data); -+ if (!saved_cred) { -+ pr_err("sdcardfs: failed to set up .nomedia in %s: %d\n", -+ lower_path.dentry->d_name.name, -+ -ENOMEM); -+ goto out; -+ } -+ set_fs_pwd(current->fs, &lower_path); -+ touch_err = touch(".nomedia", 0664); -+ if (touch_err) { -+ pr_err("sdcardfs: failed to create .nomedia in %s: %d\n", -+ lower_path.dentry->d_name.name, -+ touch_err); -+ goto out; -+ } -+ } -+out: -+ task_lock(current); -+ current->fs = saved_fs; -+ task_unlock(current); -+ -+ free_fs_struct(copied_fs); -+out_unlock: -+ sdcardfs_put_lower_path(dentry, &lower_path); -+out_revert: -+ revert_fsids(saved_cred); -+out_eacces: -+ return err; -+} -+ -+static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) -+{ -+ struct dentry *lower_dentry; -+ struct dentry *lower_dir_dentry; -+ struct vfsmount *lower_mnt; -+ int err; -+ struct path lower_path; -+ const struct cred *saved_cred = NULL; -+ -+ if (!check_caller_access_to_name(dir, &dentry->d_name)) { -+ err = -EACCES; -+ goto out_eacces; -+ } -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), -+ SDCARDFS_I(dir)->data); -+ if (!saved_cred) -+ return -ENOMEM; -+ -+ /* sdcardfs_get_real_lower(): in case of remove an user's obb dentry -+ * the dentry on the original path should be deleted. -+ */ -+ sdcardfs_get_real_lower(dentry, &lower_path); -+ -+ lower_dentry = lower_path.dentry; -+ lower_mnt = lower_path.mnt; -+ lower_dir_dentry = lock_parent(lower_dentry); -+ -+ err = vfs_rmdir2(lower_mnt, d_inode(lower_dir_dentry), lower_dentry); -+ if (err) -+ goto out; -+ -+ d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ -+ if (d_inode(dentry)) -+ clear_nlink(d_inode(dentry)); -+ fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry)); -+ fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry)); -+ set_nlink(dir, d_inode(lower_dir_dentry)->i_nlink); -+ -+out: -+ unlock_dir(lower_dir_dentry); -+ sdcardfs_put_real_lower(dentry, &lower_path); -+ revert_fsids(saved_cred); -+out_eacces: -+ return err; -+} -+ -+/* -+ * The locking rules in sdcardfs_rename are complex. We could use a simpler -+ * superblock-level name-space lock for renames and copy-ups. -+ */ -+static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry, -+ unsigned int flags) -+{ -+ int err = 0; -+ struct dentry *lower_old_dentry = NULL; -+ struct dentry *lower_new_dentry = NULL; -+ struct dentry *lower_old_dir_dentry = NULL; -+ struct dentry *lower_new_dir_dentry = NULL; -+ struct vfsmount *lower_mnt = NULL; -+ struct dentry *trap = NULL; -+ struct path lower_old_path, lower_new_path; -+ const struct cred *saved_cred = NULL; -+ -+ if (flags) -+ return -EINVAL; -+ -+ if (!check_caller_access_to_name(old_dir, &old_dentry->d_name) || -+ !check_caller_access_to_name(new_dir, &new_dentry->d_name)) { -+ err = -EACCES; -+ goto out_eacces; -+ } -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(SDCARDFS_SB(old_dir->i_sb), -+ SDCARDFS_I(new_dir)->data); -+ if (!saved_cred) -+ return -ENOMEM; -+ -+ sdcardfs_get_real_lower(old_dentry, &lower_old_path); -+ sdcardfs_get_lower_path(new_dentry, &lower_new_path); -+ lower_old_dentry = lower_old_path.dentry; -+ lower_new_dentry = lower_new_path.dentry; -+ lower_mnt = lower_old_path.mnt; -+ lower_old_dir_dentry = dget_parent(lower_old_dentry); -+ lower_new_dir_dentry = dget_parent(lower_new_dentry); -+ -+ trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); -+ /* source should not be ancestor of target */ -+ if (trap == lower_old_dentry) { -+ err = -EINVAL; -+ goto out; -+ } -+ /* target should not be ancestor of source */ -+ if (trap == lower_new_dentry) { -+ err = -ENOTEMPTY; -+ goto out; -+ } -+ -+ err = vfs_rename2(lower_mnt, -+ d_inode(lower_old_dir_dentry), lower_old_dentry, -+ d_inode(lower_new_dir_dentry), lower_new_dentry, -+ NULL, 0); -+ if (err) -+ goto out; -+ -+ /* Copy attrs from lower dir, but i_uid/i_gid */ -+ sdcardfs_copy_and_fix_attrs(new_dir, d_inode(lower_new_dir_dentry)); -+ fsstack_copy_inode_size(new_dir, d_inode(lower_new_dir_dentry)); -+ -+ if (new_dir != old_dir) { -+ sdcardfs_copy_and_fix_attrs(old_dir, d_inode(lower_old_dir_dentry)); -+ fsstack_copy_inode_size(old_dir, d_inode(lower_old_dir_dentry)); -+ } -+ get_derived_permission_new(new_dentry->d_parent, old_dentry, &new_dentry->d_name); -+ fixup_tmp_permissions(d_inode(old_dentry)); -+ fixup_lower_ownership(old_dentry, new_dentry->d_name.name); -+ d_invalidate(old_dentry); /* Can't fixup ownership recursively :( */ -+out: -+ unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); -+ dput(lower_old_dir_dentry); -+ dput(lower_new_dir_dentry); -+ sdcardfs_put_real_lower(old_dentry, &lower_old_path); -+ sdcardfs_put_lower_path(new_dentry, &lower_new_path); -+ revert_fsids(saved_cred); -+out_eacces: -+ return err; -+} -+ -+#if 0 -+static int sdcardfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) -+{ -+ int err; -+ struct dentry *lower_dentry; -+ struct path lower_path; -+ /* XXX readlink does not requires overriding credential */ -+ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ lower_dentry = lower_path.dentry; -+ if (!d_inode(lower_dentry)->i_op || -+ !d_inode(lower_dentry)->i_op->readlink) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ err = d_inode(lower_dentry)->i_op->readlink(lower_dentry, -+ buf, bufsiz); -+ if (err < 0) -+ goto out; -+ fsstack_copy_attr_atime(d_inode(dentry), d_inode(lower_dentry)); -+ -+out: -+ sdcardfs_put_lower_path(dentry, &lower_path); -+ return err; -+} -+#endif -+ -+#if 0 -+static const char *sdcardfs_follow_link(struct dentry *dentry, void **cookie) -+{ -+ char *buf; -+ int len = PAGE_SIZE, err; -+ mm_segment_t old_fs; -+ -+ /* This is freed by the put_link method assuming a successful call. */ -+ buf = kmalloc(len, GFP_KERNEL); -+ if (!buf) { -+ buf = ERR_PTR(-ENOMEM); -+ return buf; -+ } -+ -+ /* read the symlink, and then we will follow it */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = sdcardfs_readlink(dentry, buf, len); -+ set_fs(old_fs); -+ if (err < 0) { -+ kfree(buf); -+ buf = ERR_PTR(err); -+ } else { -+ buf[err] = '\0'; -+ } -+ return *cookie = buf; -+} -+#endif -+ -+static int sdcardfs_permission_wrn(struct inode *inode, int mask) -+{ -+ WARN_RATELIMIT(1, "sdcardfs does not support permission. Use permission2.\n"); -+ return -EINVAL; -+} -+ -+void copy_attrs(struct inode *dest, const struct inode *src) -+{ -+ dest->i_mode = src->i_mode; -+ dest->i_uid = src->i_uid; -+ dest->i_gid = src->i_gid; -+ dest->i_rdev = src->i_rdev; -+ dest->i_atime = src->i_atime; -+ dest->i_mtime = src->i_mtime; -+ dest->i_ctime = src->i_ctime; -+ dest->i_blkbits = src->i_blkbits; -+ dest->i_flags = src->i_flags; -+#ifdef CONFIG_FS_POSIX_ACL -+ dest->i_acl = src->i_acl; -+#endif -+#ifdef CONFIG_SECURITY -+ dest->i_security = src->i_security; -+#endif -+} -+ -+static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int mask) -+{ -+ int err; -+ struct inode tmp; -+ struct sdcardfs_inode_data *top = top_data_get(SDCARDFS_I(inode)); -+ -+ if (IS_ERR(mnt)) -+ return PTR_ERR(mnt); -+ -+ if (!top) -+ return -EINVAL; -+ -+ /* -+ * Permission check on sdcardfs inode. -+ * Calling process should have AID_SDCARD_RW permission -+ * Since generic_permission only needs i_mode, i_uid, -+ * i_gid, and i_sb, we can create a fake inode to pass -+ * this information down in. -+ * -+ * The underlying code may attempt to take locks in some -+ * cases for features we're not using, but if that changes, -+ * locks must be dealt with to avoid undefined behavior. -+ */ -+ copy_attrs(&tmp, inode); -+ tmp.i_uid = make_kuid(&init_user_ns, top->d_uid); -+ tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, inode->i_sb, top)); -+ tmp.i_mode = (inode->i_mode & S_IFMT) -+ | get_mode(mnt, SDCARDFS_I(inode), top); -+ data_put(top); -+ tmp.i_sb = inode->i_sb; -+ if (IS_POSIXACL(inode)) -+ pr_warn("%s: This may be undefined behavior...\n", __func__); -+ err = generic_permission(&tmp, mask); -+ return err; -+} -+ -+static int sdcardfs_setattr_wrn(struct dentry *dentry, struct iattr *ia) -+{ -+ WARN_RATELIMIT(1, "sdcardfs does not support setattr. User setattr2.\n"); -+ return -EINVAL; -+} -+ -+static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct iattr *ia) -+{ -+ int err; -+ struct dentry *lower_dentry; -+ struct vfsmount *lower_mnt; -+ struct inode *inode; -+ struct inode *lower_inode; -+ struct path lower_path; -+ struct iattr lower_ia; -+ struct dentry *parent; -+ struct inode tmp; -+ struct dentry tmp_d; -+ struct sdcardfs_inode_data *top; -+ -+ const struct cred *saved_cred = NULL; -+ -+ inode = d_inode(dentry); -+ top = top_data_get(SDCARDFS_I(inode)); -+ -+ if (!top) -+ return -EINVAL; -+ -+ /* -+ * Permission check on sdcardfs inode. -+ * Calling process should have AID_SDCARD_RW permission -+ * Since generic_permission only needs i_mode, i_uid, -+ * i_gid, and i_sb, we can create a fake inode to pass -+ * this information down in. -+ * -+ * The underlying code may attempt to take locks in some -+ * cases for features we're not using, but if that changes, -+ * locks must be dealt with to avoid undefined behavior. -+ * -+ */ -+ copy_attrs(&tmp, inode); -+ tmp.i_uid = make_kuid(&init_user_ns, top->d_uid); -+ tmp.i_gid = make_kgid(&init_user_ns, get_gid(mnt, dentry->d_sb, top)); -+ tmp.i_mode = (inode->i_mode & S_IFMT) -+ | get_mode(mnt, SDCARDFS_I(inode), top); -+ tmp.i_size = i_size_read(inode); -+ data_put(top); -+ tmp.i_sb = inode->i_sb; -+ tmp_d.d_inode = &tmp; -+ -+ /* -+ * Check if user has permission to change dentry. We don't check if -+ * this user can change the lower inode: that should happen when -+ * calling notify_change on the lower inode. -+ */ -+ /* prepare our own lower struct iattr (with the lower file) */ -+ memcpy(&lower_ia, ia, sizeof(lower_ia)); -+ /* Allow touch updating timestamps. A previous permission check ensures -+ * we have write access. Changes to mode, owner, and group are ignored -+ */ -+ ia->ia_valid |= ATTR_FORCE; -+ err = setattr_prepare(&tmp_d, ia); -+ -+ if (!err) { -+ /* check the Android group ID */ -+ parent = dget_parent(dentry); -+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) -+ err = -EACCES; -+ dput(parent); -+ } -+ -+ if (err) -+ goto out_err; -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(SDCARDFS_SB(dentry->d_sb), -+ SDCARDFS_I(inode)->data); -+ if (!saved_cred) -+ return -ENOMEM; -+ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ lower_dentry = lower_path.dentry; -+ lower_mnt = lower_path.mnt; -+ lower_inode = sdcardfs_lower_inode(inode); -+ -+ if (ia->ia_valid & ATTR_FILE) -+ lower_ia.ia_file = sdcardfs_lower_file(ia->ia_file); -+ -+ lower_ia.ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE); -+ -+ /* -+ * If shrinking, first truncate upper level to cancel writing dirty -+ * pages beyond the new eof; and also if its' maxbytes is more -+ * limiting (fail with -EFBIG before making any change to the lower -+ * level). There is no need to vmtruncate the upper level -+ * afterwards in the other cases: we fsstack_copy_inode_size from -+ * the lower level. -+ */ -+ if (ia->ia_valid & ATTR_SIZE) { -+ err = inode_newsize_ok(&tmp, ia->ia_size); -+ if (err) { -+ goto out; -+ } -+ truncate_setsize(inode, ia->ia_size); -+ } -+ -+ /* -+ * mode change is for clearing setuid/setgid bits. Allow lower fs -+ * to interpret this in its own way. -+ */ -+ if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) -+ lower_ia.ia_valid &= ~ATTR_MODE; -+ -+ /* notify the (possibly copied-up) lower inode */ -+ /* -+ * Note: we use d_inode(lower_dentry), because lower_inode may be -+ * unlinked (no inode->i_sb and i_ino==0. This happens if someone -+ * tries to open(), unlink(), then ftruncate() a file. -+ */ -+ inode_lock(d_inode(lower_dentry)); -+ err = notify_change2(lower_mnt, lower_dentry, &lower_ia, /* note: lower_ia */ -+ NULL); -+ inode_unlock(d_inode(lower_dentry)); -+ if (err) -+ goto out; -+ -+ /* get attributes from the lower inode and update derived permissions */ -+ sdcardfs_copy_and_fix_attrs(inode, lower_inode); -+ -+ /* -+ * Not running fsstack_copy_inode_size(inode, lower_inode), because -+ * VFS should update our inode size, and notify_change on -+ * lower_inode should update its size. -+ */ -+ -+out: -+ sdcardfs_put_lower_path(dentry, &lower_path); -+ revert_fsids(saved_cred); -+out_err: -+ return err; -+} -+ -+static int sdcardfs_fillattr(struct vfsmount *mnt, struct inode *inode, -+ struct kstat *lower_stat, struct kstat *stat) -+{ -+ struct sdcardfs_inode_info *info = SDCARDFS_I(inode); -+ struct sdcardfs_inode_data *top = top_data_get(info); -+ struct super_block *sb = inode->i_sb; -+ -+ if (!top) -+ return -EINVAL; -+ -+ stat->dev = inode->i_sb->s_dev; -+ stat->ino = inode->i_ino; -+ stat->mode = (inode->i_mode & S_IFMT) | get_mode(mnt, info, top); -+ stat->nlink = inode->i_nlink; -+ stat->uid = make_kuid(&init_user_ns, top->d_uid); -+ stat->gid = make_kgid(&init_user_ns, get_gid(mnt, sb, top)); -+ stat->rdev = inode->i_rdev; -+ stat->size = lower_stat->size; -+ stat->atime = lower_stat->atime; -+ stat->mtime = lower_stat->mtime; -+ stat->ctime = lower_stat->ctime; -+ stat->blksize = lower_stat->blksize; -+ stat->blocks = lower_stat->blocks; -+ data_put(top); -+ return 0; -+} -+static int sdcardfs_getattr(const struct path *path, struct kstat *stat, -+ u32 request_mask, unsigned int flags) -+{ -+ struct vfsmount *mnt = path->mnt; -+ struct dentry *dentry = path->dentry; -+ struct kstat lower_stat; -+ struct path lower_path; -+ struct dentry *parent; -+ int err; -+ -+ parent = dget_parent(dentry); -+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) { -+ dput(parent); -+ return -EACCES; -+ } -+ dput(parent); -+ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ err = vfs_getattr(&lower_path, &lower_stat, request_mask, flags); -+ if (err) -+ goto out; -+ sdcardfs_copy_and_fix_attrs(d_inode(dentry), -+ d_inode(lower_path.dentry)); -+ err = sdcardfs_fillattr(mnt, d_inode(dentry), &lower_stat, stat); -+out: -+ sdcardfs_put_lower_path(dentry, &lower_path); -+ return err; -+} -+ -+const struct inode_operations sdcardfs_symlink_iops = { -+ .permission2 = sdcardfs_permission, -+ .setattr2 = sdcardfs_setattr, -+ /* XXX Following operations are implemented, -+ * but FUSE(sdcard) or FAT does not support them -+ * These methods are *NOT* perfectly tested. -+ .readlink = sdcardfs_readlink, -+ .follow_link = sdcardfs_follow_link, -+ .put_link = kfree_put_link, -+ */ -+}; -+ -+const struct inode_operations sdcardfs_dir_iops = { -+ .create = sdcardfs_create, -+ .lookup = sdcardfs_lookup, -+ .permission = sdcardfs_permission_wrn, -+ .permission2 = sdcardfs_permission, -+ .unlink = sdcardfs_unlink, -+ .mkdir = sdcardfs_mkdir, -+ .rmdir = sdcardfs_rmdir, -+ .rename = sdcardfs_rename, -+ .setattr = sdcardfs_setattr_wrn, -+ .setattr2 = sdcardfs_setattr, -+ .getattr = sdcardfs_getattr, -+}; -+ -+const struct inode_operations sdcardfs_main_iops = { -+ .permission = sdcardfs_permission_wrn, -+ .permission2 = sdcardfs_permission, -+ .setattr = sdcardfs_setattr_wrn, -+ .setattr2 = sdcardfs_setattr, -+ .getattr = sdcardfs_getattr, -+}; -diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c -new file mode 100644 -index 000000000000..a5c9686090e0 ---- /dev/null -+++ b/fs/sdcardfs/lookup.c -@@ -0,0 +1,470 @@ -+/* -+ * fs/sdcardfs/lookup.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+#include "linux/delay.h" -+ -+/* The dentry cache is just so we have properly sized dentries */ -+static struct kmem_cache *sdcardfs_dentry_cachep; -+ -+int sdcardfs_init_dentry_cache(void) -+{ -+ sdcardfs_dentry_cachep = -+ kmem_cache_create("sdcardfs_dentry", -+ sizeof(struct sdcardfs_dentry_info), -+ 0, SLAB_RECLAIM_ACCOUNT, NULL); -+ -+ return sdcardfs_dentry_cachep ? 0 : -ENOMEM; -+} -+ -+void sdcardfs_destroy_dentry_cache(void) -+{ -+ kmem_cache_destroy(sdcardfs_dentry_cachep); -+} -+ -+void free_dentry_private_data(struct dentry *dentry) -+{ -+ kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata); -+ dentry->d_fsdata = NULL; -+} -+ -+/* allocate new dentry private data */ -+int new_dentry_private_data(struct dentry *dentry) -+{ -+ struct sdcardfs_dentry_info *info = SDCARDFS_D(dentry); -+ -+ /* use zalloc to init dentry_info.lower_path */ -+ info = kmem_cache_zalloc(sdcardfs_dentry_cachep, GFP_ATOMIC); -+ if (!info) -+ return -ENOMEM; -+ -+ spin_lock_init(&info->lock); -+ dentry->d_fsdata = info; -+ -+ return 0; -+} -+ -+struct inode_data { -+ struct inode *lower_inode; -+ userid_t id; -+}; -+ -+static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/) -+{ -+ struct inode *current_lower_inode = sdcardfs_lower_inode(inode); -+ userid_t current_userid = SDCARDFS_I(inode)->data->userid; -+ -+ if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode && -+ current_userid == ((struct inode_data *)candidate_data)->id) -+ return 1; /* found a match */ -+ else -+ return 0; /* no match */ -+} -+ -+static int sdcardfs_inode_set(struct inode *inode, void *lower_inode) -+{ -+ /* we do actual inode initialization in sdcardfs_iget */ -+ return 0; -+} -+ -+struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id) -+{ -+ struct sdcardfs_inode_info *info; -+ struct inode_data data; -+ struct inode *inode; /* the new inode to return */ -+ -+ if (!igrab(lower_inode)) -+ return ERR_PTR(-ESTALE); -+ -+ data.id = id; -+ data.lower_inode = lower_inode; -+ inode = iget5_locked(sb, /* our superblock */ -+ /* -+ * hashval: we use inode number, but we can -+ * also use "(unsigned long)lower_inode" -+ * instead. -+ */ -+ lower_inode->i_ino, /* hashval */ -+ sdcardfs_inode_test, /* inode comparison function */ -+ sdcardfs_inode_set, /* inode init function */ -+ &data); /* data passed to test+set fxns */ -+ if (!inode) { -+ iput(lower_inode); -+ return ERR_PTR(-ENOMEM); -+ } -+ /* if found a cached inode, then just return it (after iput) */ -+ if (!(inode->i_state & I_NEW)) { -+ iput(lower_inode); -+ return inode; -+ } -+ -+ /* initialize new inode */ -+ info = SDCARDFS_I(inode); -+ -+ inode->i_ino = lower_inode->i_ino; -+ sdcardfs_set_lower_inode(inode, lower_inode); -+ -+ inode_inc_iversion_raw(inode); -+ -+ /* use different set of inode ops for symlinks & directories */ -+ if (S_ISDIR(lower_inode->i_mode)) -+ inode->i_op = &sdcardfs_dir_iops; -+ else if (S_ISLNK(lower_inode->i_mode)) -+ inode->i_op = &sdcardfs_symlink_iops; -+ else -+ inode->i_op = &sdcardfs_main_iops; -+ -+ /* use different set of file ops for directories */ -+ if (S_ISDIR(lower_inode->i_mode)) -+ inode->i_fop = &sdcardfs_dir_fops; -+ else -+ inode->i_fop = &sdcardfs_main_fops; -+ -+ inode->i_mapping->a_ops = &sdcardfs_aops; -+ -+ inode->i_atime.tv_sec = 0; -+ inode->i_atime.tv_nsec = 0; -+ inode->i_mtime.tv_sec = 0; -+ inode->i_mtime.tv_nsec = 0; -+ inode->i_ctime.tv_sec = 0; -+ inode->i_ctime.tv_nsec = 0; -+ -+ /* properly initialize special inodes */ -+ if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) || -+ S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) -+ init_special_inode(inode, lower_inode->i_mode, -+ lower_inode->i_rdev); -+ -+ /* all well, copy inode attributes */ -+ sdcardfs_copy_and_fix_attrs(inode, lower_inode); -+ fsstack_copy_inode_size(inode, lower_inode); -+ -+ unlock_new_inode(inode); -+ return inode; -+} -+ -+/* -+ * Helper interpose routine, called directly by ->lookup to handle -+ * spliced dentries. -+ */ -+static struct dentry *__sdcardfs_interpose(struct dentry *dentry, -+ struct super_block *sb, -+ struct path *lower_path, -+ userid_t id) -+{ -+ struct inode *inode; -+ struct inode *lower_inode; -+ struct super_block *lower_sb; -+ struct dentry *ret_dentry; -+ -+ lower_inode = d_inode(lower_path->dentry); -+ lower_sb = sdcardfs_lower_super(sb); -+ -+ /* check that the lower file system didn't cross a mount point */ -+ if (lower_inode->i_sb != lower_sb) { -+ ret_dentry = ERR_PTR(-EXDEV); -+ goto out; -+ } -+ -+ /* -+ * We allocate our new inode below by calling sdcardfs_iget, -+ * which will initialize some of the new inode's fields -+ */ -+ -+ /* inherit lower inode number for sdcardfs's inode */ -+ inode = sdcardfs_iget(sb, lower_inode, id); -+ if (IS_ERR(inode)) { -+ ret_dentry = ERR_CAST(inode); -+ goto out; -+ } -+ -+ ret_dentry = d_splice_alias(inode, dentry); -+ dentry = ret_dentry ?: dentry; -+ if (!IS_ERR(dentry)) -+ update_derived_permission_lock(dentry); -+out: -+ return ret_dentry; -+} -+ -+/* -+ * Connect an sdcardfs inode dentry/inode with several lower ones. This is -+ * the classic stackable file system "vnode interposition" action. -+ * -+ * @dentry: sdcardfs's dentry which interposes on lower one -+ * @sb: sdcardfs's super_block -+ * @lower_path: the lower path (caller does path_get/put) -+ */ -+int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, -+ struct path *lower_path, userid_t id) -+{ -+ struct dentry *ret_dentry; -+ -+ ret_dentry = __sdcardfs_interpose(dentry, sb, lower_path, id); -+ return PTR_ERR(ret_dentry); -+} -+ -+struct sdcardfs_name_data { -+ struct dir_context ctx; -+ const struct qstr *to_find; -+ char *name; -+ bool found; -+}; -+ -+static int sdcardfs_name_match(struct dir_context *ctx, const char *name, -+ int namelen, loff_t offset, u64 ino, unsigned int d_type) -+{ -+ struct sdcardfs_name_data *buf = container_of(ctx, struct sdcardfs_name_data, ctx); -+ struct qstr candidate = QSTR_INIT(name, namelen); -+ -+ if (qstr_case_eq(buf->to_find, &candidate)) { -+ memcpy(buf->name, name, namelen); -+ buf->name[namelen] = 0; -+ buf->found = true; -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * Main driver function for sdcardfs's lookup. -+ * -+ * Returns: NULL (ok), ERR_PTR if an error occurred. -+ * Fills in lower_parent_path with on success. -+ */ -+static struct dentry *__sdcardfs_lookup(struct dentry *dentry, -+ unsigned int flags, struct path *lower_parent_path, userid_t id) -+{ -+ int err = 0; -+ struct vfsmount *lower_dir_mnt; -+ struct dentry *lower_dir_dentry = NULL; -+ struct dentry *lower_dentry; -+ const struct qstr *name; -+ struct path lower_path; -+ struct qstr dname; -+ struct dentry *ret_dentry = NULL; -+ struct sdcardfs_sb_info *sbi; -+ -+ sbi = SDCARDFS_SB(dentry->d_sb); -+ /* must initialize dentry operations */ -+ d_set_d_op(dentry, &sdcardfs_ci_dops); -+ -+ if (IS_ROOT(dentry)) -+ goto out; -+ -+ name = &dentry->d_name; -+ -+ /* now start the actual lookup procedure */ -+ lower_dir_dentry = lower_parent_path->dentry; -+ lower_dir_mnt = lower_parent_path->mnt; -+ -+ /* Use vfs_path_lookup to check if the dentry exists or not */ -+ err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0, -+ &lower_path); -+ /* check for other cases */ -+ if (err == -ENOENT) { -+ struct file *file; -+ const struct cred *cred = current_cred(); -+ -+ struct sdcardfs_name_data buffer = { -+ .ctx.actor = sdcardfs_name_match, -+ .to_find = name, -+ .name = __getname(), -+ .found = false, -+ }; -+ -+ if (!buffer.name) { -+ err = -ENOMEM; -+ goto out; -+ } -+ file = dentry_open(lower_parent_path, O_RDONLY, cred); -+ if (IS_ERR(file)) { -+ err = PTR_ERR(file); -+ goto put_name; -+ } -+ err = iterate_dir(file, &buffer.ctx); -+ fput(file); -+ if (err) -+ goto put_name; -+ -+ if (buffer.found) -+ err = vfs_path_lookup(lower_dir_dentry, -+ lower_dir_mnt, -+ buffer.name, 0, -+ &lower_path); -+ else -+ err = -ENOENT; -+put_name: -+ __putname(buffer.name); -+ } -+ -+ /* no error: handle positive dentries */ -+ if (!err) { -+ /* check if the dentry is an obb dentry -+ * if true, the lower_inode must be replaced with -+ * the inode of the graft path -+ */ -+ -+ if (need_graft_path(dentry)) { -+ -+ /* setup_obb_dentry() -+ * The lower_path will be stored to the dentry's orig_path -+ * and the base obbpath will be copyed to the lower_path variable. -+ * if an error returned, there's no change in the lower_path -+ * returns: -ERRNO if error (0: no error) -+ */ -+ err = setup_obb_dentry(dentry, &lower_path); -+ -+ if (err) { -+ /* if the sbi->obbpath is not available, we can optionally -+ * setup the lower_path with its orig_path. -+ * but, the current implementation just returns an error -+ * because the sdcard daemon also regards this case as -+ * a lookup fail. -+ */ -+ pr_info("sdcardfs: base obbpath is not available\n"); -+ sdcardfs_put_reset_orig_path(dentry); -+ goto out; -+ } -+ } -+ -+ sdcardfs_set_lower_path(dentry, &lower_path); -+ ret_dentry = -+ __sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id); -+ if (IS_ERR(ret_dentry)) { -+ err = PTR_ERR(ret_dentry); -+ /* path_put underlying path on error */ -+ sdcardfs_put_reset_lower_path(dentry); -+ } -+ goto out; -+ } -+ -+ /* -+ * We don't consider ENOENT an error, and we want to return a -+ * negative dentry. -+ */ -+ if (err && err != -ENOENT) -+ goto out; -+ -+ /* instatiate a new negative dentry */ -+ dname.name = name->name; -+ dname.len = name->len; -+ -+ /* See if the low-level filesystem might want -+ * to use its own hash -+ */ -+ lower_dentry = d_hash_and_lookup(lower_dir_dentry, &dname); -+ if (IS_ERR(lower_dentry)) -+ return lower_dentry; -+ -+ if (!lower_dentry) { -+ /* We called vfs_path_lookup earlier, and did not get a negative -+ * dentry then. Don't confuse the lower filesystem by forcing -+ * one on it now... -+ */ -+ err = -ENOENT; -+ goto out; -+ } -+ -+ lower_path.dentry = lower_dentry; -+ lower_path.mnt = mntget(lower_dir_mnt); -+ sdcardfs_set_lower_path(dentry, &lower_path); -+ -+ /* -+ * If the intent is to create a file, then don't return an error, so -+ * the VFS will continue the process of making this negative dentry -+ * into a positive one. -+ */ -+ if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET)) -+ err = 0; -+ -+out: -+ if (err) -+ return ERR_PTR(err); -+ return ret_dentry; -+} -+ -+/* -+ * On success: -+ * fills dentry object appropriate values and returns NULL. -+ * On fail (== error) -+ * returns error ptr -+ * -+ * @dir : Parent inode. -+ * @dentry : Target dentry to lookup. we should set each of fields. -+ * (dentry->d_name is initialized already) -+ * @nd : nameidata of parent inode -+ */ -+struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, -+ unsigned int flags) -+{ -+ struct dentry *ret = NULL, *parent; -+ struct path lower_parent_path; -+ int err = 0; -+ const struct cred *saved_cred = NULL; -+ -+ parent = dget_parent(dentry); -+ -+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) { -+ ret = ERR_PTR(-EACCES); -+ goto out_err; -+ } -+ -+ /* save current_cred and override it */ -+ saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb), -+ SDCARDFS_I(dir)->data); -+ if (!saved_cred) { -+ ret = ERR_PTR(-ENOMEM); -+ goto out_err; -+ } -+ -+ sdcardfs_get_lower_path(parent, &lower_parent_path); -+ -+ /* allocate dentry private data. We free it in ->d_release */ -+ err = new_dentry_private_data(dentry); -+ if (err) { -+ ret = ERR_PTR(err); -+ goto out; -+ } -+ -+ ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, -+ SDCARDFS_I(dir)->data->userid); -+ if (IS_ERR(ret)) -+ goto out; -+ if (ret) -+ dentry = ret; -+ if (d_inode(dentry)) { -+ fsstack_copy_attr_times(d_inode(dentry), -+ sdcardfs_lower_inode(d_inode(dentry))); -+ /* get derived permission */ -+ get_derived_permission(parent, dentry); -+ fixup_tmp_permissions(d_inode(dentry)); -+ fixup_lower_ownership(dentry, dentry->d_name.name); -+ } -+ /* update parent directory's atime */ -+ fsstack_copy_attr_atime(d_inode(parent), -+ sdcardfs_lower_inode(d_inode(parent))); -+ -+out: -+ sdcardfs_put_lower_path(parent, &lower_parent_path); -+ revert_fsids(saved_cred); -+out_err: -+ dput(parent); -+ return ret; -+} -diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c -new file mode 100644 -index 000000000000..b8e5cf2b9ae5 ---- /dev/null -+++ b/fs/sdcardfs/main.c -@@ -0,0 +1,454 @@ -+/* -+ * fs/sdcardfs/main.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+#include -+#include -+#include -+#include -+#include -+ -+enum sdcardfs_param { -+ Opt_fsuid, -+ Opt_fsgid, -+ Opt_gid, -+ Opt_debug, -+ Opt_mask, -+ Opt_multiuser, -+ Opt_userid, -+ Opt_reserved_mb, -+ Opt_gid_derivation, -+ Opt_default_normal, -+ Opt_nocache, -+ Opt_unshared_obb, -+ Opt_err, -+}; -+ -+static const struct fs_parameter_spec sdcardfs_param_specs[] = { -+ fsparam_u32("fsuid", Opt_fsuid), -+ fsparam_u32("fsgid", Opt_fsgid), -+ fsparam_u32("gid", Opt_gid), -+ fsparam_bool("debug", Opt_debug), -+ fsparam_u32("mask", Opt_mask), -+ fsparam_u32("userid", Opt_userid), -+ fsparam_bool("multiuser", Opt_multiuser), -+ fsparam_bool("derive_gid", Opt_gid_derivation), -+ fsparam_bool("default_normal", Opt_default_normal), -+ fsparam_bool("unshared_obb", Opt_unshared_obb), -+ fsparam_u32("reserved_mb", Opt_reserved_mb), -+ fsparam_bool("nocache", Opt_nocache), -+ {} -+}; -+ -+static const struct fs_parameter_description sdcardfs_parameters = { -+ .name = "sdcardfs", -+ .specs = sdcardfs_param_specs, -+}; -+ -+static int sdcardfs_parse_param(struct fs_context *fc, struct fs_parameter *param) -+{ -+ struct sdcardfs_context_options *fc_opts = fc->fs_private; -+ struct sdcardfs_mount_options *opts = &fc_opts->opts; -+ struct sdcardfs_vfsmount_options *vfsopts = &fc_opts->vfsopts; -+ struct fs_parse_result result; -+ int opt; -+ -+ opt = fs_parse(fc, &sdcardfs_parameters, param, &result); -+ if (opt < 0) -+ return opt; -+ -+ switch (opt) { -+ case Opt_debug: -+ opts->debug = true; -+ case Opt_fsuid: -+ opts->fs_low_uid = result.uint_32; -+ break; -+ case Opt_fsgid: -+ opts->fs_low_gid = result.uint_32; -+ break; -+ case Opt_gid: -+ vfsopts->gid = result.uint_32; -+ break; -+ case Opt_userid: -+ opts->fs_user_id = result.uint_32; -+ break; -+ case Opt_mask: -+ vfsopts->mask = result.uint_32; -+ break; -+ case Opt_multiuser: -+ opts->multiuser = true; -+ break; -+ case Opt_reserved_mb: -+ opts->reserved_mb = result.uint_32; -+ break; -+ case Opt_gid_derivation: -+ opts->gid_derivation = true; -+ break; -+ case Opt_default_normal: -+ opts->default_normal = true; -+ break; -+ case Opt_nocache: -+ opts->nocache = true; -+ break; -+ case Opt_unshared_obb: -+ opts->unshared_obb = true; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static void copy_sb_opts(struct sdcardfs_mount_options *opts, -+ struct fs_context *fc) -+{ -+ struct sdcardfs_context_options *fcopts = fc->fs_private; -+ -+ opts->debug = fcopts->opts.debug; -+ opts->default_normal = fcopts->opts.default_normal; -+ opts->fs_low_gid = fcopts->opts.fs_low_gid; -+ opts->fs_low_uid = fcopts->opts.fs_low_uid; -+ opts->fs_user_id = fcopts->opts.fs_user_id; -+ opts->gid_derivation = fcopts->opts.gid_derivation; -+ opts->multiuser = fcopts->opts.multiuser; -+ opts->nocache = fcopts->opts.nocache; -+ opts->reserved_mb = fcopts->opts.reserved_mb; -+ opts->unshared_obb = fcopts->opts.unshared_obb; -+} -+ -+#if 0 -+/* -+ * our custom d_alloc_root work-alike -+ * -+ * we can't use d_alloc_root if we want to use our own interpose function -+ * unchanged, so we simply call our own "fake" d_alloc_root -+ */ -+static struct dentry *sdcardfs_d_alloc_root(struct super_block *sb) -+{ -+ struct dentry *ret = NULL; -+ -+ if (sb) { -+ static const struct qstr name = { -+ .name = "/", -+ .len = 1 -+ }; -+ -+ ret = d_alloc(NULL, &name); -+ if (ret) { -+ d_set_d_op(ret, &sdcardfs_ci_dops); -+ ret->d_sb = sb; -+ ret->d_parent = ret; -+ } -+ } -+ return ret; -+} -+#endif -+ -+DEFINE_MUTEX(sdcardfs_super_list_lock); -+EXPORT_SYMBOL_GPL(sdcardfs_super_list_lock); -+LIST_HEAD(sdcardfs_super_list); -+EXPORT_SYMBOL_GPL(sdcardfs_super_list); -+ -+struct sdcardfs_mount_private { -+ struct vfsmount *mnt; -+ const char *dev_name; -+ void *raw_data; -+}; -+ -+static int __sdcardfs_fill_super( -+ struct super_block *sb, -+ struct fs_context *fc) -+{ -+ int err = 0; -+ struct super_block *lower_sb; -+ struct path lower_path; -+ struct sdcardfs_sb_info *sb_info; -+ struct inode *inode; -+ const char *dev_name = fc->source; -+ struct sdcardfs_context_options *fcopts = fc->fs_private; -+ struct sdcardfs_mount_options *opts = &fcopts->opts; -+ struct sdcardfs_vfsmount_options *mntopts = &fcopts->vfsopts; -+ -+ pr_info("sdcardfs version 2.0\n"); -+ -+ if (!dev_name) { -+ pr_err("sdcardfs: read_super: missing dev_name argument\n"); -+ err = -EINVAL; -+ goto out; -+ } -+ -+ pr_info("sdcardfs: dev_name -> %s\n", dev_name); -+ pr_info("sdcardfs: gid=%d,mask=%x\n", mntopts->gid, mntopts->mask); -+ -+ /* parse lower path */ -+ err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, -+ &lower_path); -+ if (err) { -+ pr_err("sdcardfs: error accessing lower directory '%s'\n", dev_name); -+ goto out; -+ } -+ -+ /* allocate superblock private data */ -+ sb->s_fs_info = kzalloc(sizeof(struct sdcardfs_sb_info), GFP_KERNEL); -+ if (!SDCARDFS_SB(sb)) { -+ pr_crit("sdcardfs: read_super: out of memory\n"); -+ err = -ENOMEM; -+ goto out_free; -+ } -+ -+ sb_info = sb->s_fs_info; -+ copy_sb_opts(&sb_info->options, fc); -+ if (opts->debug) { -+ pr_info("sdcardfs : options - debug:%d\n", opts->debug); -+ pr_info("sdcardfs : options - gid:%d\n", mntopts->gid); -+ pr_info("sdcardfs : options - mask:%d\n", mntopts->mask); -+ } -+ -+ /* set the lower superblock field of upper superblock */ -+ lower_sb = lower_path.dentry->d_sb; -+ atomic_inc(&lower_sb->s_active); -+ sdcardfs_set_lower_super(sb, lower_sb); -+ -+ sb->s_stack_depth = lower_sb->s_stack_depth + 1; -+ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { -+ pr_err("sdcardfs: maximum fs stacking depth exceeded\n"); -+ err = -EINVAL; -+ goto out_sput; -+ } -+ -+ /* inherit maxbytes from lower file system */ -+ sb->s_maxbytes = lower_sb->s_maxbytes; -+ -+ /* -+ * Our c/m/atime granularity is 1 ns because we may stack on file -+ * systems whose granularity is as good. -+ */ -+ sb->s_time_gran = 1; -+ -+ sb->s_magic = SDCARDFS_SUPER_MAGIC; -+ sb->s_op = &sdcardfs_sops; -+ -+ /* get a new inode and allocate our root dentry */ -+ inode = sdcardfs_iget(sb, d_inode(lower_path.dentry), 0); -+ if (IS_ERR(inode)) { -+ err = PTR_ERR(inode); -+ goto out_sput; -+ } -+ sb->s_root = d_make_root(inode); -+ if (!sb->s_root) { -+ err = -ENOMEM; -+ goto out_sput; -+ } -+ d_set_d_op(sb->s_root, &sdcardfs_ci_dops); -+ -+ /* link the upper and lower dentries */ -+ sb->s_root->d_fsdata = NULL; -+ err = new_dentry_private_data(sb->s_root); -+ if (err) -+ goto out_freeroot; -+ -+ /* set the lower dentries for s_root */ -+ sdcardfs_set_lower_path(sb->s_root, &lower_path); -+ -+ /* -+ * No need to call interpose because we already have a positive -+ * dentry, which was instantiated by d_make_root. Just need to -+ * d_rehash it. -+ */ -+ d_rehash(sb->s_root); -+ -+ /* setup permission policy */ -+ sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL); -+ mutex_lock(&sdcardfs_super_list_lock); -+ if (sb_info->options.multiuser) { -+ setup_derived_state(d_inode(sb->s_root), PERM_PRE_ROOT, -+ sb_info->options.fs_user_id, AID_ROOT); -+ snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name); -+ } else { -+ setup_derived_state(d_inode(sb->s_root), PERM_ROOT, -+ sb_info->options.fs_user_id, AID_ROOT); -+ snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name); -+ } -+ fixup_tmp_permissions(d_inode(sb->s_root)); -+ sb_info->sb = sb; -+ list_add(&sb_info->list, &sdcardfs_super_list); -+ mutex_unlock(&sdcardfs_super_list_lock); -+ -+ if (!(fc->sb_flags & SB_SILENT)) -+ pr_info("sdcardfs: mounted on top of %s type %s\n", -+ dev_name, lower_sb->s_type->name); -+ goto out; /* all is well */ -+ -+ /* no longer needed: free_dentry_private_data(sb->s_root); */ -+out_freeroot: -+ dput(sb->s_root); -+ sb->s_root = NULL; -+out_sput: -+ /* drop refs we took earlier */ -+ atomic_dec(&lower_sb->s_active); -+ kfree(SDCARDFS_SB(sb)); -+ sb->s_fs_info = NULL; -+out_free: -+ path_put(&lower_path); -+ -+out: -+ return err; -+} -+ -+static int sdcardfs_get_tree(struct fs_context *fc) -+{ -+ return vfs_get_super(fc, vfs_get_independent_super, -+ __sdcardfs_fill_super); -+} -+ -+void *sdcardfs_alloc_mnt_data(void) -+{ -+ return kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL); -+} -+ -+void sdcardfs_kill_sb(struct super_block *sb) -+{ -+ struct sdcardfs_sb_info *sbi; -+ -+ if (sb->s_magic == SDCARDFS_SUPER_MAGIC && sb->s_fs_info) { -+ sbi = SDCARDFS_SB(sb); -+ mutex_lock(&sdcardfs_super_list_lock); -+ list_del(&sbi->list); -+ mutex_unlock(&sdcardfs_super_list_lock); -+ } -+ kill_anon_super(sb); -+} -+ -+static void sdcardfs_free_fs_context(struct fs_context *fc) -+{ -+ struct sdcardfs_context_options *fc_opts = fc->fs_private; -+ -+ kfree(fc_opts); -+} -+ -+/* Most of the remount happens in sdcardfs_update_mnt_data */ -+static int sdcardfs_reconfigure_context(struct fs_context *fc) -+{ -+ struct sdcardfs_context_options *fc_opts = fc->fs_private; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(fc->root->d_sb); -+ -+ sbi->options.debug = fc_opts->opts.debug; -+ if (sbi->options.debug) { -+ pr_info("sdcardfs : options - debug:%d\n", sbi->options.debug); -+ pr_info("sdcardfs : options - gid:%d\n", fc_opts->vfsopts.gid); -+ pr_info("sdcardfs : options - mask:%d\n", -+ fc_opts->vfsopts.mask); -+ } -+ return 0; -+} -+ -+/* reconfigure is handled by sdcardfs_update_mnt_data */ -+static const struct fs_context_operations sdcardfs_context_options_ops = { -+ -+ .parse_param = sdcardfs_parse_param, -+ .get_tree = sdcardfs_get_tree, -+ .free = sdcardfs_free_fs_context, -+ .reconfigure = sdcardfs_reconfigure_context, -+}; -+ -+static int sdcardfs_init_fs_context(struct fs_context *fc) -+{ -+ struct sdcardfs_context_options *fc_opts = -+ kmalloc(sizeof(struct sdcardfs_context_options), GFP_KERNEL); -+ -+ /* by default, we use AID_MEDIA_RW as uid, gid */ -+ fc_opts->opts.fs_low_uid = AID_MEDIA_RW; -+ fc_opts->opts.fs_low_gid = AID_MEDIA_RW; -+ fc_opts->opts.fs_user_id = 0; -+ fc_opts->vfsopts.gid = 0; -+ fc_opts->vfsopts.mask = 0; -+ -+ /* by default, 0MB is reserved */ -+ fc_opts->opts.reserved_mb = 0; -+ /* by default, gid derivation is off */ -+ fc_opts->opts.gid_derivation = false; -+ fc_opts->opts.default_normal = false; -+ fc_opts->opts.nocache = false; -+ fc_opts->opts.multiuser = false; -+ fc_opts->opts.debug = false; -+ -+ fc->fs_private = fc_opts; -+ fc->ops = &sdcardfs_context_options_ops; -+ return 0; -+} -+ -+static struct file_system_type sdcardfs_fs_type = { -+ .owner = THIS_MODULE, -+ .name = SDCARDFS_NAME, -+ .alloc_mnt_data = sdcardfs_alloc_mnt_data, -+ .kill_sb = sdcardfs_kill_sb, -+ .init_fs_context = sdcardfs_init_fs_context, -+ .fs_flags = 0, -+}; -+MODULE_ALIAS_FS(SDCARDFS_NAME); -+ -+static int __init init_sdcardfs_fs(void) -+{ -+ int err; -+ -+ pr_info("Registering sdcardfs " SDCARDFS_VERSION "\n"); -+ -+ err = sdcardfs_init_inode_cache(); -+ if (err) -+ goto out; -+ err = sdcardfs_init_dentry_cache(); -+ if (err) -+ goto out; -+ err = packagelist_init(); -+ if (err) -+ goto out; -+ err = register_filesystem(&sdcardfs_fs_type); -+out: -+ if (err) { -+ sdcardfs_destroy_inode_cache(); -+ sdcardfs_destroy_dentry_cache(); -+ packagelist_exit(); -+ } -+ return err; -+} -+ -+static void __exit exit_sdcardfs_fs(void) -+{ -+ sdcardfs_destroy_inode_cache(); -+ sdcardfs_destroy_dentry_cache(); -+ packagelist_exit(); -+ unregister_filesystem(&sdcardfs_fs_type); -+ pr_info("Completed sdcardfs module unload\n"); -+} -+ -+/* Original wrapfs authors */ -+MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University (http://www.fsl.cs.sunysb.edu/)"); -+ -+/* Original sdcardfs authors */ -+MODULE_AUTHOR("Woojoong Lee, Daeho Jeong, Kitae Lee, Yeongjin Gil System Memory Lab., Samsung Electronics"); -+ -+/* Current maintainer */ -+MODULE_AUTHOR("Daniel Rosenberg, Google"); -+MODULE_DESCRIPTION("Sdcardfs " SDCARDFS_VERSION); -+MODULE_LICENSE("GPL"); -+ -+module_init(init_sdcardfs_fs); -+module_exit(exit_sdcardfs_fs); -diff --git a/fs/sdcardfs/mmap.c b/fs/sdcardfs/mmap.c -new file mode 100644 -index 000000000000..0ec0950c2447 ---- /dev/null -+++ b/fs/sdcardfs/mmap.c -@@ -0,0 +1,87 @@ -+/* -+ * fs/sdcardfs/mmap.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+ -+static vm_fault_t sdcardfs_fault(struct vm_fault *vmf) -+{ -+ vm_fault_t err; -+ struct file *file; -+ const struct vm_operations_struct *lower_vm_ops; -+ -+ file = (struct file *)vmf->vma->vm_private_data; -+ lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops; -+ BUG_ON(!lower_vm_ops); -+ -+ err = lower_vm_ops->fault(vmf); -+ return err; -+} -+ -+static void sdcardfs_vm_open(struct vm_area_struct *vma) -+{ -+ struct file *file = (struct file *)vma->vm_private_data; -+ -+ get_file(file); -+} -+ -+static void sdcardfs_vm_close(struct vm_area_struct *vma) -+{ -+ struct file *file = (struct file *)vma->vm_private_data; -+ -+ fput(file); -+} -+ -+static vm_fault_t sdcardfs_page_mkwrite(struct vm_fault *vmf) -+{ -+ vm_fault_t err = 0; -+ struct file *file; -+ const struct vm_operations_struct *lower_vm_ops; -+ -+ file = (struct file *)vmf->vma->vm_private_data; -+ lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops; -+ BUG_ON(!lower_vm_ops); -+ if (!lower_vm_ops->page_mkwrite) -+ goto out; -+ -+ err = lower_vm_ops->page_mkwrite(vmf); -+out: -+ return err; -+} -+ -+static ssize_t sdcardfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) -+{ -+ /* -+ * This function should never be called directly. We need it -+ * to exist, to get past a check in open_check_o_direct(), -+ * which is called from do_last(). -+ */ -+ return -EINVAL; -+} -+ -+const struct address_space_operations sdcardfs_aops = { -+ .direct_IO = sdcardfs_direct_IO, -+}; -+ -+const struct vm_operations_struct sdcardfs_vm_ops = { -+ .fault = sdcardfs_fault, -+ .page_mkwrite = sdcardfs_page_mkwrite, -+ .open = sdcardfs_vm_open, -+ .close = sdcardfs_vm_close, -+}; -diff --git a/fs/sdcardfs/multiuser.h b/fs/sdcardfs/multiuser.h -new file mode 100644 -index 000000000000..85341e753f8c ---- /dev/null -+++ b/fs/sdcardfs/multiuser.h -@@ -0,0 +1,53 @@ -+/* -+ * fs/sdcardfs/multiuser.h -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#define AID_USER_OFFSET 100000 /* offset for uid ranges for each user */ -+#define AID_APP_START 10000 /* first app user */ -+#define AID_APP_END 19999 /* last app user */ -+#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */ -+#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */ -+#define AID_EXT_CACHE_GID_START 40000 /* start of gids for apps to mark external cached data */ -+#define AID_EXT_CACHE_GID_END 49999 /* end of gids for apps to mark external cached data */ -+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ -+ -+typedef uid_t userid_t; -+typedef uid_t appid_t; -+ -+static inline uid_t multiuser_get_uid(userid_t user_id, appid_t app_id) -+{ -+ return (user_id * AID_USER_OFFSET) + (app_id % AID_USER_OFFSET); -+} -+ -+static inline bool uid_is_app(uid_t uid) -+{ -+ appid_t appid = uid % AID_USER_OFFSET; -+ -+ return appid >= AID_APP_START && appid <= AID_APP_END; -+} -+ -+static inline gid_t multiuser_get_ext_cache_gid(uid_t uid) -+{ -+ return uid - AID_APP_START + AID_EXT_CACHE_GID_START; -+} -+ -+static inline gid_t multiuser_get_ext_gid(uid_t uid) -+{ -+ return uid - AID_APP_START + AID_EXT_GID_START; -+} -diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c -new file mode 100644 -index 000000000000..4b9a5635f1e0 ---- /dev/null -+++ b/fs/sdcardfs/packagelist.c -@@ -0,0 +1,882 @@ -+/* -+ * fs/sdcardfs/packagelist.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include "sdcardfs.h" -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+struct hashtable_entry { -+ struct hlist_node hlist; -+ struct hlist_node dlist; /* for deletion cleanup */ -+ struct qstr key; -+ atomic_t value; -+}; -+ -+static DEFINE_HASHTABLE(package_to_appid, 8); -+static DEFINE_HASHTABLE(package_to_userid, 8); -+static DEFINE_HASHTABLE(ext_to_groupid, 8); -+ -+ -+static struct kmem_cache *hashtable_entry_cachep; -+ -+static unsigned int full_name_case_hash(const void *salt, const unsigned char *name, unsigned int len) -+{ -+ unsigned long hash = init_name_hash(salt); -+ -+ while (len--) -+ hash = partial_name_hash(tolower(*name++), hash); -+ return end_name_hash(hash); -+} -+ -+static inline void qstr_init(struct qstr *q, const char *name) -+{ -+ q->name = name; -+ q->len = strlen(q->name); -+ q->hash = full_name_case_hash(0, q->name, q->len); -+} -+ -+static inline int qstr_copy(const struct qstr *src, struct qstr *dest) -+{ -+ dest->name = kstrdup(src->name, GFP_KERNEL); -+ dest->hash_len = src->hash_len; -+ return !!dest->name; -+} -+ -+ -+static appid_t __get_appid(const struct qstr *key) -+{ -+ struct hashtable_entry *hash_cur; -+ unsigned int hash = key->hash; -+ appid_t ret_id; -+ -+ rcu_read_lock(); -+ hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key)) { -+ ret_id = atomic_read(&hash_cur->value); -+ rcu_read_unlock(); -+ return ret_id; -+ } -+ } -+ rcu_read_unlock(); -+ return 0; -+} -+ -+appid_t get_appid(const char *key) -+{ -+ struct qstr q; -+ -+ qstr_init(&q, key); -+ return __get_appid(&q); -+} -+ -+static appid_t __get_ext_gid(const struct qstr *key) -+{ -+ struct hashtable_entry *hash_cur; -+ unsigned int hash = key->hash; -+ appid_t ret_id; -+ -+ rcu_read_lock(); -+ hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key)) { -+ ret_id = atomic_read(&hash_cur->value); -+ rcu_read_unlock(); -+ return ret_id; -+ } -+ } -+ rcu_read_unlock(); -+ return 0; -+} -+ -+appid_t get_ext_gid(const char *key) -+{ -+ struct qstr q; -+ -+ qstr_init(&q, key); -+ return __get_ext_gid(&q); -+} -+ -+static appid_t __is_excluded(const struct qstr *app_name, userid_t user) -+{ -+ struct hashtable_entry *hash_cur; -+ unsigned int hash = app_name->hash; -+ -+ rcu_read_lock(); -+ hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) { -+ if (atomic_read(&hash_cur->value) == user && -+ qstr_case_eq(app_name, &hash_cur->key)) { -+ rcu_read_unlock(); -+ return 1; -+ } -+ } -+ rcu_read_unlock(); -+ return 0; -+} -+ -+appid_t is_excluded(const char *key, userid_t user) -+{ -+ struct qstr q; -+ qstr_init(&q, key); -+ return __is_excluded(&q, user); -+} -+ -+/* Kernel has already enforced everything we returned through -+ * derive_permissions_locked(), so this is used to lock down access -+ * even further, such as enforcing that apps hold sdcard_rw. -+ */ -+int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name) -+{ -+ struct qstr q_autorun = QSTR_LITERAL("autorun.inf"); -+ struct qstr q__android_secure = QSTR_LITERAL(".android_secure"); -+ struct qstr q_android_secure = QSTR_LITERAL("android_secure"); -+ -+ /* Always block security-sensitive files at root */ -+ if (parent_node && SDCARDFS_I(parent_node)->data->perm == PERM_ROOT) { -+ if (qstr_case_eq(name, &q_autorun) -+ || qstr_case_eq(name, &q__android_secure) -+ || qstr_case_eq(name, &q_android_secure)) { -+ return 0; -+ } -+ } -+ -+ /* Root always has access; access for any other UIDs should always -+ * be controlled through packages.list. -+ */ -+ if (from_kuid(&init_user_ns, current_fsuid()) == 0) -+ return 1; -+ -+ /* No extra permissions to enforce */ -+ return 1; -+} -+ -+static struct hashtable_entry *alloc_hashtable_entry(const struct qstr *key, -+ appid_t value) -+{ -+ struct hashtable_entry *ret = kmem_cache_alloc(hashtable_entry_cachep, -+ GFP_KERNEL); -+ if (!ret) -+ return NULL; -+ INIT_HLIST_NODE(&ret->dlist); -+ INIT_HLIST_NODE(&ret->hlist); -+ -+ if (!qstr_copy(key, &ret->key)) { -+ kmem_cache_free(hashtable_entry_cachep, ret); -+ return NULL; -+ } -+ -+ atomic_set(&ret->value, value); -+ return ret; -+} -+ -+static int insert_packagelist_appid_entry_locked(const struct qstr *key, appid_t value) -+{ -+ struct hashtable_entry *hash_cur; -+ struct hashtable_entry *new_entry; -+ unsigned int hash = key->hash; -+ -+ hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key)) { -+ atomic_set(&hash_cur->value, value); -+ return 0; -+ } -+ } -+ new_entry = alloc_hashtable_entry(key, value); -+ if (!new_entry) -+ return -ENOMEM; -+ hash_add_rcu(package_to_appid, &new_entry->hlist, hash); -+ return 0; -+} -+ -+static int insert_ext_gid_entry_locked(const struct qstr *key, appid_t value) -+{ -+ struct hashtable_entry *hash_cur; -+ struct hashtable_entry *new_entry; -+ unsigned int hash = key->hash; -+ -+ /* An extension can only belong to one gid */ -+ hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key)) -+ return -EINVAL; -+ } -+ new_entry = alloc_hashtable_entry(key, value); -+ if (!new_entry) -+ return -ENOMEM; -+ hash_add_rcu(ext_to_groupid, &new_entry->hlist, hash); -+ return 0; -+} -+ -+static int insert_userid_exclude_entry_locked(const struct qstr *key, userid_t value) -+{ -+ struct hashtable_entry *hash_cur; -+ struct hashtable_entry *new_entry; -+ unsigned int hash = key->hash; -+ -+ /* Only insert if not already present */ -+ hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) { -+ if (atomic_read(&hash_cur->value) == value && -+ qstr_case_eq(key, &hash_cur->key)) -+ return 0; -+ } -+ new_entry = alloc_hashtable_entry(key, value); -+ if (!new_entry) -+ return -ENOMEM; -+ hash_add_rcu(package_to_userid, &new_entry->hlist, hash); -+ return 0; -+} -+ -+static void fixup_all_perms_name(const struct qstr *key) -+{ -+ struct sdcardfs_sb_info *sbinfo; -+ struct limit_search limit = { -+ .flags = BY_NAME, -+ .name = QSTR_INIT(key->name, key->len), -+ }; -+ list_for_each_entry(sbinfo, &sdcardfs_super_list, list) { -+ if (sbinfo_has_sdcard_magic(sbinfo)) -+ fixup_perms_recursive(sbinfo->sb->s_root, &limit); -+ } -+} -+ -+static void fixup_all_perms_name_userid(const struct qstr *key, userid_t userid) -+{ -+ struct sdcardfs_sb_info *sbinfo; -+ struct limit_search limit = { -+ .flags = BY_NAME | BY_USERID, -+ .name = QSTR_INIT(key->name, key->len), -+ .userid = userid, -+ }; -+ list_for_each_entry(sbinfo, &sdcardfs_super_list, list) { -+ if (sbinfo_has_sdcard_magic(sbinfo)) -+ fixup_perms_recursive(sbinfo->sb->s_root, &limit); -+ } -+} -+ -+static void fixup_all_perms_userid(userid_t userid) -+{ -+ struct sdcardfs_sb_info *sbinfo; -+ struct limit_search limit = { -+ .flags = BY_USERID, -+ .userid = userid, -+ }; -+ list_for_each_entry(sbinfo, &sdcardfs_super_list, list) { -+ if (sbinfo_has_sdcard_magic(sbinfo)) -+ fixup_perms_recursive(sbinfo->sb->s_root, &limit); -+ } -+} -+ -+static int insert_packagelist_entry(const struct qstr *key, appid_t value) -+{ -+ int err; -+ -+ mutex_lock(&sdcardfs_super_list_lock); -+ err = insert_packagelist_appid_entry_locked(key, value); -+ if (!err) -+ fixup_all_perms_name(key); -+ mutex_unlock(&sdcardfs_super_list_lock); -+ -+ return err; -+} -+ -+static int insert_ext_gid_entry(const struct qstr *key, appid_t value) -+{ -+ int err; -+ -+ mutex_lock(&sdcardfs_super_list_lock); -+ err = insert_ext_gid_entry_locked(key, value); -+ mutex_unlock(&sdcardfs_super_list_lock); -+ -+ return err; -+} -+ -+static int insert_userid_exclude_entry(const struct qstr *key, userid_t value) -+{ -+ int err; -+ -+ mutex_lock(&sdcardfs_super_list_lock); -+ err = insert_userid_exclude_entry_locked(key, value); -+ if (!err) -+ fixup_all_perms_name_userid(key, value); -+ mutex_unlock(&sdcardfs_super_list_lock); -+ -+ return err; -+} -+ -+static void free_hashtable_entry(struct hashtable_entry *entry) -+{ -+ kfree(entry->key.name); -+ kmem_cache_free(hashtable_entry_cachep, entry); -+} -+ -+static void remove_packagelist_entry_locked(const struct qstr *key) -+{ -+ struct hashtable_entry *hash_cur; -+ unsigned int hash = key->hash; -+ struct hlist_node *h_t; -+ HLIST_HEAD(free_list); -+ -+ hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key)) { -+ hash_del_rcu(&hash_cur->hlist); -+ hlist_add_head(&hash_cur->dlist, &free_list); -+ } -+ } -+ hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key)) { -+ hash_del_rcu(&hash_cur->hlist); -+ hlist_add_head(&hash_cur->dlist, &free_list); -+ break; -+ } -+ } -+ synchronize_rcu(); -+ hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist) -+ free_hashtable_entry(hash_cur); -+} -+ -+static void remove_packagelist_entry(const struct qstr *key) -+{ -+ mutex_lock(&sdcardfs_super_list_lock); -+ remove_packagelist_entry_locked(key); -+ fixup_all_perms_name(key); -+ mutex_unlock(&sdcardfs_super_list_lock); -+} -+ -+static void remove_ext_gid_entry_locked(const struct qstr *key, gid_t group) -+{ -+ struct hashtable_entry *hash_cur; -+ unsigned int hash = key->hash; -+ -+ hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key) && atomic_read(&hash_cur->value) == group) { -+ hash_del_rcu(&hash_cur->hlist); -+ synchronize_rcu(); -+ free_hashtable_entry(hash_cur); -+ break; -+ } -+ } -+} -+ -+static void remove_ext_gid_entry(const struct qstr *key, gid_t group) -+{ -+ mutex_lock(&sdcardfs_super_list_lock); -+ remove_ext_gid_entry_locked(key, group); -+ mutex_unlock(&sdcardfs_super_list_lock); -+} -+ -+static void remove_userid_all_entry_locked(userid_t userid) -+{ -+ struct hashtable_entry *hash_cur; -+ struct hlist_node *h_t; -+ HLIST_HEAD(free_list); -+ int i; -+ -+ hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) { -+ if (atomic_read(&hash_cur->value) == userid) { -+ hash_del_rcu(&hash_cur->hlist); -+ hlist_add_head(&hash_cur->dlist, &free_list); -+ } -+ } -+ synchronize_rcu(); -+ hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist) { -+ free_hashtable_entry(hash_cur); -+ } -+} -+ -+static void remove_userid_all_entry(userid_t userid) -+{ -+ mutex_lock(&sdcardfs_super_list_lock); -+ remove_userid_all_entry_locked(userid); -+ fixup_all_perms_userid(userid); -+ mutex_unlock(&sdcardfs_super_list_lock); -+} -+ -+static void remove_userid_exclude_entry_locked(const struct qstr *key, userid_t userid) -+{ -+ struct hashtable_entry *hash_cur; -+ unsigned int hash = key->hash; -+ -+ hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(key, &hash_cur->key) && -+ atomic_read(&hash_cur->value) == userid) { -+ hash_del_rcu(&hash_cur->hlist); -+ synchronize_rcu(); -+ free_hashtable_entry(hash_cur); -+ break; -+ } -+ } -+} -+ -+static void remove_userid_exclude_entry(const struct qstr *key, userid_t userid) -+{ -+ mutex_lock(&sdcardfs_super_list_lock); -+ remove_userid_exclude_entry_locked(key, userid); -+ fixup_all_perms_name_userid(key, userid); -+ mutex_unlock(&sdcardfs_super_list_lock); -+} -+ -+static void packagelist_destroy(void) -+{ -+ struct hashtable_entry *hash_cur; -+ struct hlist_node *h_t; -+ HLIST_HEAD(free_list); -+ int i; -+ -+ mutex_lock(&sdcardfs_super_list_lock); -+ hash_for_each_rcu(package_to_appid, i, hash_cur, hlist) { -+ hash_del_rcu(&hash_cur->hlist); -+ hlist_add_head(&hash_cur->dlist, &free_list); -+ } -+ hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) { -+ hash_del_rcu(&hash_cur->hlist); -+ hlist_add_head(&hash_cur->dlist, &free_list); -+ } -+ synchronize_rcu(); -+ hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist) -+ free_hashtable_entry(hash_cur); -+ mutex_unlock(&sdcardfs_super_list_lock); -+ pr_info("sdcardfs: destroyed packagelist pkgld\n"); -+} -+ -+#define SDCARDFS_CONFIGFS_ATTR(_pfx, _name) \ -+static struct configfs_attribute _pfx##attr_##_name = { \ -+ .ca_name = __stringify(_name), \ -+ .ca_mode = S_IRUGO | S_IWUGO, \ -+ .ca_owner = THIS_MODULE, \ -+ .show = _pfx##_name##_show, \ -+ .store = _pfx##_name##_store, \ -+} -+ -+#define SDCARDFS_CONFIGFS_ATTR_RO(_pfx, _name) \ -+static struct configfs_attribute _pfx##attr_##_name = { \ -+ .ca_name = __stringify(_name), \ -+ .ca_mode = S_IRUGO, \ -+ .ca_owner = THIS_MODULE, \ -+ .show = _pfx##_name##_show, \ -+} -+ -+#define SDCARDFS_CONFIGFS_ATTR_WO(_pfx, _name) \ -+static struct configfs_attribute _pfx##attr_##_name = { \ -+ .ca_name = __stringify(_name), \ -+ .ca_mode = S_IWUGO, \ -+ .ca_owner = THIS_MODULE, \ -+ .store = _pfx##_name##_store, \ -+} -+ -+struct package_details { -+ struct config_item item; -+ struct qstr name; -+}; -+ -+static inline struct package_details *to_package_details(struct config_item *item) -+{ -+ return item ? container_of(item, struct package_details, item) : NULL; -+} -+ -+static ssize_t package_details_appid_show(struct config_item *item, char *page) -+{ -+ return scnprintf(page, PAGE_SIZE, "%u\n", __get_appid(&to_package_details(item)->name)); -+} -+ -+static ssize_t package_details_appid_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ unsigned int tmp; -+ int ret; -+ -+ ret = kstrtouint(page, 10, &tmp); -+ if (ret) -+ return ret; -+ -+ ret = insert_packagelist_entry(&to_package_details(item)->name, tmp); -+ -+ if (ret) -+ return ret; -+ -+ return count; -+} -+ -+static ssize_t package_details_excluded_userids_show(struct config_item *item, -+ char *page) -+{ -+ struct package_details *package_details = to_package_details(item); -+ struct hashtable_entry *hash_cur; -+ unsigned int hash = package_details->name.hash; -+ int count = 0; -+ -+ rcu_read_lock(); -+ hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) { -+ if (qstr_case_eq(&package_details->name, &hash_cur->key)) -+ count += scnprintf(page + count, PAGE_SIZE - count, -+ "%d ", atomic_read(&hash_cur->value)); -+ } -+ rcu_read_unlock(); -+ if (count) -+ count--; -+ count += scnprintf(page + count, PAGE_SIZE - count, "\n"); -+ return count; -+} -+ -+static ssize_t package_details_excluded_userids_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ unsigned int tmp; -+ int ret; -+ -+ ret = kstrtouint(page, 10, &tmp); -+ if (ret) -+ return ret; -+ -+ ret = insert_userid_exclude_entry(&to_package_details(item)->name, tmp); -+ -+ if (ret) -+ return ret; -+ -+ return count; -+} -+ -+static ssize_t package_details_clear_userid_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ unsigned int tmp; -+ int ret; -+ -+ ret = kstrtouint(page, 10, &tmp); -+ if (ret) -+ return ret; -+ remove_userid_exclude_entry(&to_package_details(item)->name, tmp); -+ return count; -+} -+ -+static void package_details_release(struct config_item *item) -+{ -+ struct package_details *package_details = to_package_details(item); -+ -+ pr_info("sdcardfs: removing %s\n", package_details->name.name); -+ remove_packagelist_entry(&package_details->name); -+ kfree(package_details->name.name); -+ kfree(package_details); -+} -+ -+SDCARDFS_CONFIGFS_ATTR(package_details_, appid); -+SDCARDFS_CONFIGFS_ATTR(package_details_, excluded_userids); -+SDCARDFS_CONFIGFS_ATTR_WO(package_details_, clear_userid); -+ -+static struct configfs_attribute *package_details_attrs[] = { -+ &package_details_attr_appid, -+ &package_details_attr_excluded_userids, -+ &package_details_attr_clear_userid, -+ NULL, -+}; -+ -+static struct configfs_item_operations package_details_item_ops = { -+ .release = package_details_release, -+}; -+ -+static struct config_item_type package_appid_type = { -+ .ct_item_ops = &package_details_item_ops, -+ .ct_attrs = package_details_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct extensions_value { -+ struct config_group group; -+ unsigned int num; -+}; -+ -+struct extension_details { -+ struct config_item item; -+ struct qstr name; -+ unsigned int num; -+}; -+ -+static inline struct extensions_value *to_extensions_value(struct config_item *item) -+{ -+ return item ? container_of(to_config_group(item), struct extensions_value, group) : NULL; -+} -+ -+static inline struct extension_details *to_extension_details(struct config_item *item) -+{ -+ return item ? container_of(item, struct extension_details, item) : NULL; -+} -+ -+static void extension_details_release(struct config_item *item) -+{ -+ struct extension_details *extension_details = to_extension_details(item); -+ -+ pr_info("sdcardfs: No longer mapping %s files to gid %d\n", -+ extension_details->name.name, extension_details->num); -+ remove_ext_gid_entry(&extension_details->name, extension_details->num); -+ kfree(extension_details->name.name); -+ kfree(extension_details); -+} -+ -+static struct configfs_item_operations extension_details_item_ops = { -+ .release = extension_details_release, -+}; -+ -+static struct config_item_type extension_details_type = { -+ .ct_item_ops = &extension_details_item_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *extension_details_make_item(struct config_group *group, const char *name) -+{ -+ struct extensions_value *extensions_value = to_extensions_value(&group->cg_item); -+ struct extension_details *extension_details = kzalloc(sizeof(struct extension_details), GFP_KERNEL); -+ const char *tmp; -+ int ret; -+ -+ if (!extension_details) -+ return ERR_PTR(-ENOMEM); -+ -+ tmp = kstrdup(name, GFP_KERNEL); -+ if (!tmp) { -+ kfree(extension_details); -+ return ERR_PTR(-ENOMEM); -+ } -+ qstr_init(&extension_details->name, tmp); -+ extension_details->num = extensions_value->num; -+ ret = insert_ext_gid_entry(&extension_details->name, extensions_value->num); -+ -+ if (ret) { -+ kfree(extension_details->name.name); -+ kfree(extension_details); -+ return ERR_PTR(ret); -+ } -+ config_item_init_type_name(&extension_details->item, name, &extension_details_type); -+ -+ return &extension_details->item; -+} -+ -+static struct configfs_group_operations extensions_value_group_ops = { -+ .make_item = extension_details_make_item, -+}; -+ -+static struct config_item_type extensions_name_type = { -+ .ct_group_ops = &extensions_value_group_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_group *extensions_make_group(struct config_group *group, const char *name) -+{ -+ struct extensions_value *extensions_value; -+ unsigned int tmp; -+ int ret; -+ -+ extensions_value = kzalloc(sizeof(struct extensions_value), GFP_KERNEL); -+ if (!extensions_value) -+ return ERR_PTR(-ENOMEM); -+ ret = kstrtouint(name, 10, &tmp); -+ if (ret) { -+ kfree(extensions_value); -+ return ERR_PTR(ret); -+ } -+ -+ extensions_value->num = tmp; -+ config_group_init_type_name(&extensions_value->group, name, -+ &extensions_name_type); -+ return &extensions_value->group; -+} -+ -+static void extensions_drop_group(struct config_group *group, struct config_item *item) -+{ -+ struct extensions_value *value = to_extensions_value(item); -+ -+ pr_info("sdcardfs: No longer mapping any files to gid %d\n", value->num); -+ kfree(value); -+} -+ -+static struct configfs_group_operations extensions_group_ops = { -+ .make_group = extensions_make_group, -+ .drop_item = extensions_drop_group, -+}; -+ -+static struct config_item_type extensions_type = { -+ .ct_group_ops = &extensions_group_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group extension_group = { -+ .cg_item = { -+ .ci_namebuf = "extensions", -+ .ci_type = &extensions_type, -+ }, -+}; -+ -+static struct config_item *packages_make_item(struct config_group *group, const char *name) -+{ -+ struct package_details *package_details; -+ const char *tmp; -+ -+ package_details = kzalloc(sizeof(struct package_details), GFP_KERNEL); -+ if (!package_details) -+ return ERR_PTR(-ENOMEM); -+ tmp = kstrdup(name, GFP_KERNEL); -+ if (!tmp) { -+ kfree(package_details); -+ return ERR_PTR(-ENOMEM); -+ } -+ qstr_init(&package_details->name, tmp); -+ config_item_init_type_name(&package_details->item, name, -+ &package_appid_type); -+ -+ return &package_details->item; -+} -+ -+static ssize_t packages_list_show(struct config_item *item, char *page) -+{ -+ struct hashtable_entry *hash_cur_app; -+ struct hashtable_entry *hash_cur_user; -+ int i; -+ int count = 0, written = 0; -+ const char errormsg[] = "\n"; -+ unsigned int hash; -+ -+ rcu_read_lock(); -+ hash_for_each_rcu(package_to_appid, i, hash_cur_app, hlist) { -+ written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n", -+ hash_cur_app->key.name, atomic_read(&hash_cur_app->value)); -+ hash = hash_cur_app->key.hash; -+ hash_for_each_possible_rcu(package_to_userid, hash_cur_user, hlist, hash) { -+ if (qstr_case_eq(&hash_cur_app->key, &hash_cur_user->key)) { -+ written += scnprintf(page + count + written - 1, -+ PAGE_SIZE - sizeof(errormsg) - count - written + 1, -+ " %d\n", atomic_read(&hash_cur_user->value)) - 1; -+ } -+ } -+ if (count + written == PAGE_SIZE - sizeof(errormsg) - 1) { -+ count += scnprintf(page + count, PAGE_SIZE - count, errormsg); -+ break; -+ } -+ count += written; -+ } -+ rcu_read_unlock(); -+ -+ return count; -+} -+ -+static ssize_t packages_remove_userid_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ unsigned int tmp; -+ int ret; -+ -+ ret = kstrtouint(page, 10, &tmp); -+ if (ret) -+ return ret; -+ remove_userid_all_entry(tmp); -+ return count; -+} -+ -+static struct configfs_attribute packages_attr_packages_gid_list = { -+ .ca_name = "packages_gid.list", -+ .ca_mode = S_IRUGO, -+ .ca_owner = THIS_MODULE, -+ .show = packages_list_show, -+}; -+ -+SDCARDFS_CONFIGFS_ATTR_WO(packages_, remove_userid); -+ -+static struct configfs_attribute *packages_attrs[] = { -+ &packages_attr_packages_gid_list, -+ &packages_attr_remove_userid, -+ NULL, -+}; -+ -+/* -+ * Note that, since no extra work is required on ->drop_item(), -+ * no ->drop_item() is provided. -+ */ -+static struct configfs_group_operations packages_group_ops = { -+ .make_item = packages_make_item, -+}; -+ -+static struct config_item_type packages_type = { -+ .ct_group_ops = &packages_group_ops, -+ .ct_attrs = packages_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group *sd_default_groups[] = { -+ &extension_group, -+ NULL, -+}; -+ -+static struct configfs_subsystem sdcardfs_packages = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "sdcardfs", -+ .ci_type = &packages_type, -+ }, -+ }, -+}; -+ -+static int configfs_sdcardfs_init(void) -+{ -+ int ret, i; -+ struct configfs_subsystem *subsys = &sdcardfs_packages; -+ -+ config_group_init(&subsys->su_group); -+ for (i = 0; sd_default_groups[i]; i++) { -+ config_group_init(sd_default_groups[i]); -+ configfs_add_default_group(sd_default_groups[i], &subsys->su_group); -+ } -+ mutex_init(&subsys->su_mutex); -+ ret = configfs_register_subsystem(subsys); -+ if (ret) { -+ pr_err("Error %d while registering subsystem %s\n", -+ ret, -+ subsys->su_group.cg_item.ci_namebuf); -+ } -+ return ret; -+} -+ -+static void configfs_sdcardfs_exit(void) -+{ -+ configfs_unregister_subsystem(&sdcardfs_packages); -+} -+ -+int packagelist_init(void) -+{ -+ hashtable_entry_cachep = -+ kmem_cache_create("packagelist_hashtable_entry", -+ sizeof(struct hashtable_entry), 0, 0, NULL); -+ if (!hashtable_entry_cachep) { -+ pr_err("sdcardfs: failed creating pkgl_hashtable entry slab cache\n"); -+ return -ENOMEM; -+ } -+ -+ configfs_sdcardfs_init(); -+ return 0; -+} -+ -+void packagelist_exit(void) -+{ -+ configfs_sdcardfs_exit(); -+ packagelist_destroy(); -+ kmem_cache_destroy(hashtable_entry_cachep); -+} -diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h -new file mode 100644 -index 000000000000..f813d23cddcd ---- /dev/null -+++ b/fs/sdcardfs/sdcardfs.h -@@ -0,0 +1,662 @@ -+/* -+ * fs/sdcardfs/sdcardfs.h -+ * -+ * The sdcardfs v2.0 -+ * This file system replaces the sdcard daemon on Android -+ * On version 2.0, some of the daemon functions have been ported -+ * to support the multi-user concepts of Android 4.4 -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#ifndef _SDCARDFS_H_ -+#define _SDCARDFS_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "multiuser.h" -+ -+/* the file system name */ -+#define SDCARDFS_NAME "sdcardfs" -+ -+/* sdcardfs root inode number */ -+#define SDCARDFS_ROOT_INO 1 -+ -+/* useful for tracking code reachability */ -+#define UDBG pr_default("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__) -+ -+#define SDCARDFS_DIRENT_SIZE 256 -+ -+/* temporary static uid settings for development */ -+#define AID_ROOT 0 /* uid for accessing /mnt/sdcard & extSdcard */ -+#define AID_MEDIA_RW 1023 /* internal media storage write access */ -+ -+#define AID_SDCARD_RW 1015 /* external storage write access */ -+#define AID_SDCARD_R 1028 /* external storage read access */ -+#define AID_SDCARD_PICS 1033 /* external storage photos access */ -+#define AID_SDCARD_AV 1034 /* external storage audio/video access */ -+#define AID_SDCARD_ALL 1035 /* access all users external storage */ -+#define AID_MEDIA_OBB 1059 /* obb files */ -+ -+#define AID_SDCARD_IMAGE 1057 -+ -+#define AID_PACKAGE_INFO 1027 -+ -+ -+/* -+ * Permissions are handled by our permission function. -+ * We don't want anyone who happens to look at our inode value to prematurely -+ * block access, so store more permissive values. These are probably never -+ * used. -+ */ -+#define fixup_tmp_permissions(x) \ -+ do { \ -+ (x)->i_uid = make_kuid(&init_user_ns, \ -+ SDCARDFS_I(x)->data->d_uid); \ -+ (x)->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW); \ -+ (x)->i_mode = ((x)->i_mode & S_IFMT) | 0775;\ -+ } while (0) -+ -+/* Android 5.0 support */ -+ -+/* Permission mode for a specific node. Controls how file permissions -+ * are derived for children nodes. -+ */ -+typedef enum { -+ /* Nothing special; this node should just inherit from its parent. */ -+ PERM_INHERIT, -+ /* This node is one level above a normal root; used for legacy layouts -+ * which use the first level to represent user_id. -+ */ -+ PERM_PRE_ROOT, -+ /* This node is "/" */ -+ PERM_ROOT, -+ /* This node is "/Android" */ -+ PERM_ANDROID, -+ /* This node is "/Android/data" */ -+ PERM_ANDROID_DATA, -+ /* This node is "/Android/obb" */ -+ PERM_ANDROID_OBB, -+ /* This node is "/Android/media" */ -+ PERM_ANDROID_MEDIA, -+ /* This node is "/Android/[data|media|obb]/[package]" */ -+ PERM_ANDROID_PACKAGE, -+ /* This node is "/Android/[data|media|obb]/[package]/cache" */ -+ PERM_ANDROID_PACKAGE_CACHE, -+} perm_t; -+ -+struct sdcardfs_sb_info; -+struct sdcardfs_mount_options; -+struct sdcardfs_inode_info; -+struct sdcardfs_inode_data; -+ -+/* Do not directly use this function. Use OVERRIDE_CRED() instead. */ -+const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, -+ struct sdcardfs_inode_data *data); -+/* Do not directly use this function, use REVERT_CRED() instead. */ -+void revert_fsids(const struct cred *old_cred); -+ -+/* operations vectors defined in specific files */ -+extern const struct file_operations sdcardfs_main_fops; -+extern const struct file_operations sdcardfs_dir_fops; -+extern const struct inode_operations sdcardfs_main_iops; -+extern const struct inode_operations sdcardfs_dir_iops; -+extern const struct inode_operations sdcardfs_symlink_iops; -+extern const struct super_operations sdcardfs_sops; -+extern const struct dentry_operations sdcardfs_ci_dops; -+extern const struct address_space_operations sdcardfs_aops, sdcardfs_dummy_aops; -+extern const struct vm_operations_struct sdcardfs_vm_ops; -+ -+extern int sdcardfs_init_inode_cache(void); -+extern void sdcardfs_destroy_inode_cache(void); -+extern int sdcardfs_init_dentry_cache(void); -+extern void sdcardfs_destroy_dentry_cache(void); -+extern int new_dentry_private_data(struct dentry *dentry); -+extern void free_dentry_private_data(struct dentry *dentry); -+extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, -+ unsigned int flags); -+extern struct inode *sdcardfs_iget(struct super_block *sb, -+ struct inode *lower_inode, userid_t id); -+extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, -+ struct path *lower_path, userid_t id); -+ -+/* file private data */ -+struct sdcardfs_file_info { -+ struct file *lower_file; -+ const struct vm_operations_struct *lower_vm_ops; -+}; -+ -+struct sdcardfs_inode_data { -+ struct kref refcount; -+ bool abandoned; -+ -+ perm_t perm; -+ userid_t userid; -+ uid_t d_uid; -+ bool under_android; -+ bool under_cache; -+ bool under_obb; -+}; -+ -+/* sdcardfs inode data in memory */ -+struct sdcardfs_inode_info { -+ struct inode *lower_inode; -+ /* state derived based on current position in hierarchy */ -+ struct sdcardfs_inode_data *data; -+ -+ /* top folder for ownership */ -+ spinlock_t top_lock; -+ struct sdcardfs_inode_data *top_data; -+ -+ struct inode vfs_inode; -+}; -+ -+ -+/* sdcardfs dentry data in memory */ -+struct sdcardfs_dentry_info { -+ spinlock_t lock; /* protects lower_path */ -+ struct path lower_path; -+ struct path orig_path; -+}; -+ -+struct sdcardfs_mount_options { -+ uid_t fs_low_uid; -+ gid_t fs_low_gid; -+ userid_t fs_user_id; -+ bool multiuser; -+ bool gid_derivation; -+ bool default_normal; -+ bool unshared_obb; -+ unsigned int reserved_mb; -+ bool nocache; -+ bool debug; -+}; -+ -+struct sdcardfs_vfsmount_options { -+ gid_t gid; -+ mode_t mask; -+}; -+ -+struct sdcardfs_context_options { -+ struct sdcardfs_mount_options opts; -+ struct sdcardfs_vfsmount_options vfsopts; -+}; -+ -+extern int parse_options_remount(struct super_block *sb, char *options, int silent, -+ struct sdcardfs_vfsmount_options *vfsopts); -+ -+/* sdcardfs super-block data in memory */ -+struct sdcardfs_sb_info { -+ struct super_block *sb; -+ struct super_block *lower_sb; -+ /* derived perm policy : some of options have been added -+ * to sdcardfs_mount_options (Android 4.4 support) -+ */ -+ struct sdcardfs_mount_options options; -+ spinlock_t lock; /* protects obbpath */ -+ char *obbpath_s; -+ struct path obbpath; -+ void *pkgl_id; -+ struct list_head list; -+}; -+ -+/* -+ * inode to private data -+ * -+ * Since we use containers and the struct inode is _inside_ the -+ * sdcardfs_inode_info structure, SDCARDFS_I will always (given a non-NULL -+ * inode pointer), return a valid non-NULL pointer. -+ */ -+static inline struct sdcardfs_inode_info *SDCARDFS_I(const struct inode *inode) -+{ -+ return container_of(inode, struct sdcardfs_inode_info, vfs_inode); -+} -+ -+/* dentry to private data */ -+#define SDCARDFS_D(dent) ((struct sdcardfs_dentry_info *)(dent)->d_fsdata) -+ -+/* superblock to private data */ -+#define SDCARDFS_SB(super) ((struct sdcardfs_sb_info *)(super)->s_fs_info) -+ -+/* file to private Data */ -+#define SDCARDFS_F(file) ((struct sdcardfs_file_info *)((file)->private_data)) -+ -+/* file to lower file */ -+static inline struct file *sdcardfs_lower_file(const struct file *f) -+{ -+ return SDCARDFS_F(f)->lower_file; -+} -+ -+static inline void sdcardfs_set_lower_file(struct file *f, struct file *val) -+{ -+ SDCARDFS_F(f)->lower_file = val; -+} -+ -+/* inode to lower inode. */ -+static inline struct inode *sdcardfs_lower_inode(const struct inode *i) -+{ -+ return SDCARDFS_I(i)->lower_inode; -+} -+ -+static inline void sdcardfs_set_lower_inode(struct inode *i, struct inode *val) -+{ -+ SDCARDFS_I(i)->lower_inode = val; -+} -+ -+/* superblock to lower superblock */ -+static inline struct super_block *sdcardfs_lower_super( -+ const struct super_block *sb) -+{ -+ return SDCARDFS_SB(sb)->lower_sb; -+} -+ -+static inline void sdcardfs_set_lower_super(struct super_block *sb, -+ struct super_block *val) -+{ -+ SDCARDFS_SB(sb)->lower_sb = val; -+} -+ -+/* path based (dentry/mnt) macros */ -+static inline void pathcpy(struct path *dst, const struct path *src) -+{ -+ dst->dentry = src->dentry; -+ dst->mnt = src->mnt; -+} -+ -+/* sdcardfs_get_pname functions calls path_get() -+ * therefore, the caller must call "proper" path_put functions -+ */ -+#define SDCARDFS_DENT_FUNC(pname) \ -+static inline void sdcardfs_get_##pname(const struct dentry *dent, \ -+ struct path *pname) \ -+{ \ -+ spin_lock(&SDCARDFS_D(dent)->lock); \ -+ pathcpy(pname, &SDCARDFS_D(dent)->pname); \ -+ path_get(pname); \ -+ spin_unlock(&SDCARDFS_D(dent)->lock); \ -+ return; \ -+} \ -+static inline void sdcardfs_put_##pname(const struct dentry *dent, \ -+ struct path *pname) \ -+{ \ -+ path_put(pname); \ -+ return; \ -+} \ -+static inline void sdcardfs_set_##pname(const struct dentry *dent, \ -+ struct path *pname) \ -+{ \ -+ spin_lock(&SDCARDFS_D(dent)->lock); \ -+ pathcpy(&SDCARDFS_D(dent)->pname, pname); \ -+ spin_unlock(&SDCARDFS_D(dent)->lock); \ -+ return; \ -+} \ -+static inline void sdcardfs_reset_##pname(const struct dentry *dent) \ -+{ \ -+ spin_lock(&SDCARDFS_D(dent)->lock); \ -+ SDCARDFS_D(dent)->pname.dentry = NULL; \ -+ SDCARDFS_D(dent)->pname.mnt = NULL; \ -+ spin_unlock(&SDCARDFS_D(dent)->lock); \ -+ return; \ -+} \ -+static inline void sdcardfs_put_reset_##pname(const struct dentry *dent) \ -+{ \ -+ struct path pname; \ -+ spin_lock(&SDCARDFS_D(dent)->lock); \ -+ if (SDCARDFS_D(dent)->pname.dentry) { \ -+ pathcpy(&pname, &SDCARDFS_D(dent)->pname); \ -+ SDCARDFS_D(dent)->pname.dentry = NULL; \ -+ SDCARDFS_D(dent)->pname.mnt = NULL; \ -+ spin_unlock(&SDCARDFS_D(dent)->lock); \ -+ path_put(&pname); \ -+ } else \ -+ spin_unlock(&SDCARDFS_D(dent)->lock); \ -+ return; \ -+} -+ -+SDCARDFS_DENT_FUNC(lower_path) -+SDCARDFS_DENT_FUNC(orig_path) -+ -+static inline bool sbinfo_has_sdcard_magic(struct sdcardfs_sb_info *sbinfo) -+{ -+ return sbinfo && sbinfo->sb -+ && sbinfo->sb->s_magic == SDCARDFS_SUPER_MAGIC; -+} -+ -+static inline struct sdcardfs_inode_data *data_get( -+ struct sdcardfs_inode_data *data) -+{ -+ if (data) -+ kref_get(&data->refcount); -+ return data; -+} -+ -+static inline struct sdcardfs_inode_data *top_data_get( -+ struct sdcardfs_inode_info *info) -+{ -+ struct sdcardfs_inode_data *top_data; -+ -+ spin_lock(&info->top_lock); -+ top_data = data_get(info->top_data); -+ spin_unlock(&info->top_lock); -+ return top_data; -+} -+ -+extern void data_release(struct kref *ref); -+ -+static inline void data_put(struct sdcardfs_inode_data *data) -+{ -+ kref_put(&data->refcount, data_release); -+} -+ -+static inline void release_own_data(struct sdcardfs_inode_info *info) -+{ -+ /* -+ * This happens exactly once per inode. At this point, the inode that -+ * originally held this data is about to be freed, and all references -+ * to it are held as a top value, and will likely be released soon. -+ */ -+ info->data->abandoned = true; -+ data_put(info->data); -+} -+ -+static inline void set_top(struct sdcardfs_inode_info *info, -+ struct sdcardfs_inode_info *top_owner) -+{ -+ struct sdcardfs_inode_data *old_top; -+ struct sdcardfs_inode_data *new_top = NULL; -+ -+ if (top_owner) -+ new_top = top_data_get(top_owner); -+ -+ spin_lock(&info->top_lock); -+ old_top = info->top_data; -+ info->top_data = new_top; -+ if (old_top) -+ data_put(old_top); -+ spin_unlock(&info->top_lock); -+} -+ -+static inline int get_gid(struct vfsmount *mnt, -+ struct super_block *sb, -+ struct sdcardfs_inode_data *data) -+{ -+ struct sdcardfs_vfsmount_options *vfsopts = mnt->data; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(sb); -+ -+ if (vfsopts->gid == AID_SDCARD_RW && !sbi->options.default_normal) -+ /* As an optimization, certain trusted system components only run -+ * as owner but operate across all users. Since we're now handing -+ * out the sdcard_rw GID only to trusted apps, we're okay relaxing -+ * the user boundary enforcement for the default view. The UIDs -+ * assigned to app directories are still multiuser aware. -+ */ -+ return AID_SDCARD_RW; -+ else -+ return multiuser_get_uid(data->userid, vfsopts->gid); -+} -+ -+static inline int get_mode(struct vfsmount *mnt, -+ struct sdcardfs_inode_info *info, -+ struct sdcardfs_inode_data *data) -+{ -+ int owner_mode; -+ int filtered_mode; -+ struct sdcardfs_vfsmount_options *opts = mnt->data; -+ int visible_mode = 0775 & ~opts->mask; -+ -+ -+ if (data->perm == PERM_PRE_ROOT) { -+ /* Top of multi-user view should always be visible to ensure -+ * secondary users can traverse inside. -+ */ -+ visible_mode = 0711; -+ } else if (data->under_android) { -+ /* Block "other" access to Android directories, since only apps -+ * belonging to a specific user should be in there; we still -+ * leave +x open for the default view. -+ */ -+ if (opts->gid == AID_SDCARD_RW) -+ visible_mode = visible_mode & ~0006; -+ else -+ visible_mode = visible_mode & ~0007; -+ } -+ owner_mode = info->lower_inode->i_mode & 0700; -+ filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6)); -+ return filtered_mode; -+} -+ -+static inline int has_graft_path(const struct dentry *dent) -+{ -+ int ret = 0; -+ -+ spin_lock(&SDCARDFS_D(dent)->lock); -+ if (SDCARDFS_D(dent)->orig_path.dentry != NULL) -+ ret = 1; -+ spin_unlock(&SDCARDFS_D(dent)->lock); -+ -+ return ret; -+} -+ -+static inline void sdcardfs_get_real_lower(const struct dentry *dent, -+ struct path *real_lower) -+{ -+ /* in case of a local obb dentry -+ * the orig_path should be returned -+ */ -+ if (has_graft_path(dent)) -+ sdcardfs_get_orig_path(dent, real_lower); -+ else -+ sdcardfs_get_lower_path(dent, real_lower); -+} -+ -+static inline void sdcardfs_put_real_lower(const struct dentry *dent, -+ struct path *real_lower) -+{ -+ if (has_graft_path(dent)) -+ sdcardfs_put_orig_path(dent, real_lower); -+ else -+ sdcardfs_put_lower_path(dent, real_lower); -+} -+ -+extern struct mutex sdcardfs_super_list_lock; -+extern struct list_head sdcardfs_super_list; -+ -+/* for packagelist.c */ -+extern appid_t get_appid(const char *app_name); -+extern appid_t get_ext_gid(const char *app_name); -+extern appid_t is_excluded(const char *app_name, userid_t userid); -+extern int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name); -+extern int packagelist_init(void); -+extern void packagelist_exit(void); -+ -+/* for derived_perm.c */ -+#define BY_NAME (1 << 0) -+#define BY_USERID (1 << 1) -+struct limit_search { -+ unsigned int flags; -+ struct qstr name; -+ userid_t userid; -+}; -+ -+extern void setup_derived_state(struct inode *inode, perm_t perm, -+ userid_t userid, uid_t uid); -+extern void get_derived_permission(struct dentry *parent, struct dentry *dentry); -+extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name); -+extern void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit); -+ -+extern void update_derived_permission_lock(struct dentry *dentry); -+void fixup_lower_ownership(struct dentry *dentry, const char *name); -+extern int need_graft_path(struct dentry *dentry); -+extern int is_base_obbpath(struct dentry *dentry); -+extern int is_obbpath_invalid(struct dentry *dentry); -+extern int setup_obb_dentry(struct dentry *dentry, struct path *lower_path); -+ -+/* locking helpers */ -+static inline struct dentry *lock_parent(struct dentry *dentry) -+{ -+ struct dentry *dir = dget_parent(dentry); -+ -+ inode_lock_nested(d_inode(dir), I_MUTEX_PARENT); -+ return dir; -+} -+ -+static inline void unlock_dir(struct dentry *dir) -+{ -+ inode_unlock(d_inode(dir)); -+ dput(dir); -+} -+ -+static inline int prepare_dir(const char *path_s, uid_t uid, gid_t gid, mode_t mode) -+{ -+ int err; -+ struct dentry *dent; -+ struct iattr attrs; -+ struct path parent; -+ -+ dent = kern_path_locked(path_s, &parent); -+ if (IS_ERR(dent)) { -+ err = PTR_ERR(dent); -+ if (err == -EEXIST) -+ err = 0; -+ goto out_unlock; -+ } -+ -+ err = vfs_mkdir2(parent.mnt, d_inode(parent.dentry), dent, mode); -+ if (err) { -+ if (err == -EEXIST) -+ err = 0; -+ goto out_dput; -+ } -+ -+ attrs.ia_uid = make_kuid(&init_user_ns, uid); -+ attrs.ia_gid = make_kgid(&init_user_ns, gid); -+ attrs.ia_valid = ATTR_UID | ATTR_GID; -+ inode_lock(d_inode(dent)); -+ notify_change2(parent.mnt, dent, &attrs, NULL); -+ inode_unlock(d_inode(dent)); -+ -+out_dput: -+ dput(dent); -+ -+out_unlock: -+ /* parent dentry locked by lookup_create */ -+ inode_unlock(d_inode(parent.dentry)); -+ path_put(&parent); -+ return err; -+} -+ -+/* -+ * Return 1, if a disk has enough free space, otherwise 0. -+ * We assume that any files can not be overwritten. -+ */ -+static inline int check_min_free_space(struct dentry *dentry, size_t size, int dir) -+{ -+ int err; -+ struct path lower_path; -+ struct kstatfs statfs; -+ u64 avail; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ -+ if (sbi->options.reserved_mb) { -+ /* Get fs stat of lower filesystem. */ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ err = vfs_statfs(&lower_path, &statfs); -+ sdcardfs_put_lower_path(dentry, &lower_path); -+ -+ if (unlikely(err)) -+ return 0; -+ -+ /* Invalid statfs informations. */ -+ if (unlikely(statfs.f_bsize == 0)) -+ return 0; -+ -+ /* if you are checking directory, set size to f_bsize. */ -+ if (unlikely(dir)) -+ size = statfs.f_bsize; -+ -+ /* available size */ -+ avail = statfs.f_bavail * statfs.f_bsize; -+ -+ /* not enough space */ -+ if ((u64)size > avail) -+ return 0; -+ -+ /* enough space */ -+ if ((avail - size) > (sbi->options.reserved_mb * 1024 * 1024)) -+ return 1; -+ -+ return 0; -+ } else -+ return 1; -+} -+ -+/* -+ * Copies attrs and maintains sdcardfs managed attrs -+ * Since our permission check handles all special permissions, set those to be open -+ */ -+static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct inode *src) -+{ -+ dest->i_mode = (src->i_mode & S_IFMT) | S_IRWXU | S_IRWXG | -+ S_IROTH | S_IXOTH; /* 0775 */ -+ dest->i_uid = make_kuid(&init_user_ns, SDCARDFS_I(dest)->data->d_uid); -+ dest->i_gid = make_kgid(&init_user_ns, AID_SDCARD_RW); -+ dest->i_rdev = src->i_rdev; -+ dest->i_atime = src->i_atime; -+ dest->i_mtime = src->i_mtime; -+ dest->i_ctime = src->i_ctime; -+ dest->i_blkbits = src->i_blkbits; -+ dest->i_flags = src->i_flags; -+ set_nlink(dest, src->i_nlink); -+} -+ -+static inline bool str_case_eq(const char *s1, const char *s2) -+{ -+ return !strcasecmp(s1, s2); -+} -+ -+static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len) -+{ -+ return !strncasecmp(s1, s2, len); -+} -+ -+static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2) -+{ -+ return q1->len == q2->len && str_n_case_eq(q1->name, q2->name, q2->len); -+} -+ -+#define QSTR_LITERAL(string) QSTR_INIT(string, sizeof(string)-1) -+ -+#endif /* not _SDCARDFS_H_ */ -diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c -new file mode 100644 -index 000000000000..6b1d27e5067b ---- /dev/null -+++ b/fs/sdcardfs/super.c -@@ -0,0 +1,297 @@ -+/* -+ * fs/sdcardfs/super.c -+ * -+ * Copyright (c) 2013 Samsung Electronics Co. Ltd -+ * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, -+ * Sunghwan Yun, Sungjong Seo -+ * -+ * This program has been developed as a stackable file system based on -+ * the WrapFS which written by -+ * -+ * Copyright (c) 1998-2011 Erez Zadok -+ * Copyright (c) 2009 Shrikar Archak -+ * Copyright (c) 2003-2011 Stony Brook University -+ * Copyright (c) 2003-2011 The Research Foundation of SUNY -+ * -+ * This file is dual licensed. It may be redistributed and/or modified -+ * under the terms of the Apache 2.0 License OR version 2 of the GNU -+ * General Public License. -+ */ -+ -+#include -+ -+#include "sdcardfs.h" -+ -+/* -+ * The inode cache is used with alloc_inode for both our inode info and the -+ * vfs inode. -+ */ -+static struct kmem_cache *sdcardfs_inode_cachep; -+ -+/* -+ * To support the top references, we must track some data separately. -+ * An sdcardfs_inode_info always has a reference to its data, and once set up, -+ * also has a reference to its top. The top may be itself, in which case it -+ * holds two references to its data. When top is changed, it takes a ref to the -+ * new data and then drops the ref to the old data. -+ */ -+static struct kmem_cache *sdcardfs_inode_data_cachep; -+ -+void data_release(struct kref *ref) -+{ -+ struct sdcardfs_inode_data *data = -+ container_of(ref, struct sdcardfs_inode_data, refcount); -+ -+ kmem_cache_free(sdcardfs_inode_data_cachep, data); -+} -+ -+/* final actions when unmounting a file system */ -+static void sdcardfs_put_super(struct super_block *sb) -+{ -+ struct sdcardfs_sb_info *spd; -+ struct super_block *s; -+ -+ spd = SDCARDFS_SB(sb); -+ if (!spd) -+ return; -+ -+ if (spd->obbpath_s) { -+ kfree(spd->obbpath_s); -+ path_put(&spd->obbpath); -+ } -+ -+ /* decrement lower super references */ -+ s = sdcardfs_lower_super(sb); -+ sdcardfs_set_lower_super(sb, NULL); -+ atomic_dec(&s->s_active); -+ -+ kfree(spd); -+ sb->s_fs_info = NULL; -+} -+ -+static int sdcardfs_statfs(struct dentry *dentry, struct kstatfs *buf) -+{ -+ int err; -+ struct path lower_path; -+ u32 min_blocks; -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); -+ -+ sdcardfs_get_lower_path(dentry, &lower_path); -+ err = vfs_statfs(&lower_path, buf); -+ sdcardfs_put_lower_path(dentry, &lower_path); -+ -+ if (sbi->options.reserved_mb) { -+ /* Invalid statfs informations. */ -+ if (buf->f_bsize == 0) { -+ pr_err("Returned block size is zero.\n"); -+ return -EINVAL; -+ } -+ -+ min_blocks = ((sbi->options.reserved_mb * 1024 * 1024)/buf->f_bsize); -+ buf->f_blocks -= min_blocks; -+ -+ if (buf->f_bavail > min_blocks) -+ buf->f_bavail -= min_blocks; -+ else -+ buf->f_bavail = 0; -+ -+ /* Make reserved blocks invisiable to media storage */ -+ buf->f_bfree = buf->f_bavail; -+ } -+ -+ /* set return buf to our f/s to avoid confusing user-level utils */ -+ buf->f_type = SDCARDFS_SUPER_MAGIC; -+ -+ return err; -+} -+ -+static void *sdcardfs_clone_mnt_data(void *data) -+{ -+ struct sdcardfs_vfsmount_options *opt = kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL); -+ struct sdcardfs_vfsmount_options *old = data; -+ -+ if (!opt) -+ return NULL; -+ opt->gid = old->gid; -+ opt->mask = old->mask; -+ return opt; -+} -+ -+static void sdcardfs_copy_mnt_data(void *data, void *newdata) -+{ -+ struct sdcardfs_vfsmount_options *old = data; -+ struct sdcardfs_vfsmount_options *new = newdata; -+ -+ old->gid = new->gid; -+ old->mask = new->mask; -+} -+ -+static void sdcardfs_update_mnt_data(void *data, struct fs_context *fc) -+{ -+ struct sdcardfs_vfsmount_options *opts = data; -+ struct sdcardfs_context_options *fcopts = fc->fs_private; -+ -+ opts->gid = fcopts->vfsopts.gid; -+ opts->mask = fcopts->vfsopts.mask; -+} -+ -+/* -+ * Called by iput() when the inode reference count reached zero -+ * and the inode is not hashed anywhere. Used to clear anything -+ * that needs to be, before the inode is completely destroyed and put -+ * on the inode free list. -+ */ -+static void sdcardfs_evict_inode(struct inode *inode) -+{ -+ struct inode *lower_inode; -+ -+ truncate_inode_pages(&inode->i_data, 0); -+ set_top(SDCARDFS_I(inode), NULL); -+ clear_inode(inode); -+ /* -+ * Decrement a reference to a lower_inode, which was incremented -+ * by our read_inode when it was created initially. -+ */ -+ lower_inode = sdcardfs_lower_inode(inode); -+ sdcardfs_set_lower_inode(inode, NULL); -+ iput(lower_inode); -+} -+ -+static struct inode *sdcardfs_alloc_inode(struct super_block *sb) -+{ -+ struct sdcardfs_inode_info *i; -+ struct sdcardfs_inode_data *d; -+ -+ i = kmem_cache_alloc(sdcardfs_inode_cachep, GFP_KERNEL); -+ if (!i) -+ return NULL; -+ -+ /* memset everything up to the inode to 0 */ -+ memset(i, 0, offsetof(struct sdcardfs_inode_info, vfs_inode)); -+ -+ d = kmem_cache_alloc(sdcardfs_inode_data_cachep, -+ GFP_KERNEL | __GFP_ZERO); -+ if (!d) { -+ kmem_cache_free(sdcardfs_inode_cachep, i); -+ return NULL; -+ } -+ -+ i->data = d; -+ kref_init(&d->refcount); -+ i->top_data = d; -+ spin_lock_init(&i->top_lock); -+ kref_get(&d->refcount); -+ -+ inode_set_iversion(&i->vfs_inode, 1); -+ return &i->vfs_inode; -+} -+ -+static void i_callback(struct rcu_head *head) -+{ -+ struct inode *inode = container_of(head, struct inode, i_rcu); -+ -+ release_own_data(SDCARDFS_I(inode)); -+ kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode)); -+} -+ -+static void sdcardfs_destroy_inode(struct inode *inode) -+{ -+ call_rcu(&inode->i_rcu, i_callback); -+} -+ -+/* sdcardfs inode cache constructor */ -+static void init_once(void *obj) -+{ -+ struct sdcardfs_inode_info *i = obj; -+ -+ inode_init_once(&i->vfs_inode); -+} -+ -+int sdcardfs_init_inode_cache(void) -+{ -+ sdcardfs_inode_cachep = -+ kmem_cache_create("sdcardfs_inode_cache", -+ sizeof(struct sdcardfs_inode_info), 0, -+ SLAB_RECLAIM_ACCOUNT, init_once); -+ -+ if (!sdcardfs_inode_cachep) -+ return -ENOMEM; -+ -+ sdcardfs_inode_data_cachep = -+ kmem_cache_create("sdcardfs_inode_data_cache", -+ sizeof(struct sdcardfs_inode_data), 0, -+ SLAB_RECLAIM_ACCOUNT, NULL); -+ if (!sdcardfs_inode_data_cachep) { -+ kmem_cache_destroy(sdcardfs_inode_cachep); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+/* sdcardfs inode cache destructor */ -+void sdcardfs_destroy_inode_cache(void) -+{ -+ kmem_cache_destroy(sdcardfs_inode_data_cachep); -+ kmem_cache_destroy(sdcardfs_inode_cachep); -+} -+ -+/* -+ * Used only in nfs, to kill any pending RPC tasks, so that subsequent -+ * code can actually succeed and won't leave tasks that need handling. -+ */ -+static void sdcardfs_umount_begin(struct super_block *sb) -+{ -+ struct super_block *lower_sb; -+ -+ lower_sb = sdcardfs_lower_super(sb); -+ if (lower_sb && lower_sb->s_op && lower_sb->s_op->umount_begin) -+ lower_sb->s_op->umount_begin(lower_sb); -+} -+ -+static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m, -+ struct dentry *root) -+{ -+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(root->d_sb); -+ struct sdcardfs_mount_options *opts = &sbi->options; -+ struct sdcardfs_vfsmount_options *vfsopts = mnt->data; -+ -+ if (opts->fs_low_uid != 0) -+ seq_printf(m, ",fsuid=%u", opts->fs_low_uid); -+ if (opts->fs_low_gid != 0) -+ seq_printf(m, ",fsgid=%u", opts->fs_low_gid); -+ if (vfsopts->gid != 0) -+ seq_printf(m, ",gid=%u", vfsopts->gid); -+ if (opts->multiuser) -+ seq_puts(m, ",multiuser"); -+ if (vfsopts->mask) -+ seq_printf(m, ",mask=%u", vfsopts->mask); -+ if (opts->fs_user_id) -+ seq_printf(m, ",userid=%u", opts->fs_user_id); -+ if (opts->gid_derivation) -+ seq_puts(m, ",derive_gid"); -+ if (opts->default_normal) -+ seq_puts(m, ",default_normal"); -+ if (opts->reserved_mb != 0) -+ seq_printf(m, ",reserved=%uMB", opts->reserved_mb); -+ if (opts->nocache) -+ seq_printf(m, ",nocache"); -+ if (opts->unshared_obb) -+ seq_printf(m, ",unshared_obb"); -+ -+ return 0; -+}; -+ -+const struct super_operations sdcardfs_sops = { -+ .put_super = sdcardfs_put_super, -+ .statfs = sdcardfs_statfs, -+ .clone_mnt_data = sdcardfs_clone_mnt_data, -+ .copy_mnt_data = sdcardfs_copy_mnt_data, -+ .update_mnt_data = sdcardfs_update_mnt_data, -+ .evict_inode = sdcardfs_evict_inode, -+ .umount_begin = sdcardfs_umount_begin, -+ .show_options2 = sdcardfs_show_options, -+ .alloc_inode = sdcardfs_alloc_inode, -+ .destroy_inode = sdcardfs_destroy_inode, -+ .drop_inode = generic_delete_inode, -+}; diff --git a/patches/ANDROID-sdcardfs-Define-magic-value.patch b/patches/ANDROID-sdcardfs-Define-magic-value.patch deleted file mode 100644 index c1120820ccaaed3a2ca755f5fc34dac000bed99f..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sdcardfs-Define-magic-value.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Tue, 15 Nov 2016 13:35:18 -0800 -Subject: ANDROID: sdcardfs: Define magic value - -Define a filesystem magic value to be used for sdcardfs. - -Test: HiKey/X15 + Pie + android-mainline, - and HiKey + AOSP Maser + android-mainline, - directories under /sdcard created, - output of mount is right, - CTS test collecting device infor works - -Change-Id: I54daa1452aa6a3ce0401d7d923e0a897f0c26d96 -Signed-off-by: Daniel Rosenberg -Signed-off-by: Yongqin Liu ---- - include/uapi/linux/magic.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h -index 903cc2d2750b..5c4bf0ad580c 100644 ---- a/include/uapi/linux/magic.h -+++ b/include/uapi/linux/magic.h -@@ -58,6 +58,8 @@ - #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" - #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" - -+#define SDCARDFS_SUPER_MAGIC 0x5dca2df5 -+ - #define SMB_SUPER_MAGIC 0x517B - #define CGROUP_SUPER_MAGIC 0x27e0eb - #define CGROUP2_SUPER_MAGIC 0x63677270 diff --git a/patches/ANDROID-sdcardfs-Enable-modular-sdcardfs.patch b/patches/ANDROID-sdcardfs-Enable-modular-sdcardfs.patch deleted file mode 100644 index 1c55ba2228754614ac60c648a15bcf80584ff584..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sdcardfs-Enable-modular-sdcardfs.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Tue, 30 Jan 2018 14:24:02 -0800 -Subject: ANDROID: sdcardfs: Enable modular sdcardfs - -Export the following symbols: - -- copy_fs_struct -- free_fs_struct -- security_path_chown -- set_fs_pwd -- vfs_read -- vfs_write - -These are needed to build sdcardfs as a module. - -Test: HiKey/X15 + Pie + android-mainline, - and HiKey + AOSP Maser + android-mainline, - directories under /sdcard created, - output of mount is right, - CTS test collecting device infor works - -Bug: 35142419 -Change-Id: If6e14f0b3bdc858a9f684e6c209927a9232091f0 -Signed-off-by: Daniel Rosenberg -Signed-off-by: Guenter Roeck -[astrachan: Folded the following changes into this patch: - e19f69662df5 ("ANDROID: Revert "fs: unexport vfs_read and vfs_write"") - 17071a8e1e7d ("ANDROID: fs: Export free_fs_struct and set_fs_pwd") - 2e9a639597cd ("ANDROID: export security_path_chown")] -Signed-off-by: Alistair Strachan -Signed-off-by: Yongqin Liu ---- - fs/fs_struct.c | 3 +++ - fs/read_write.c | 3 +++ - security/security.c | 1 + - 3 files changed, 7 insertions(+) - -diff --git a/fs/fs_struct.c b/fs/fs_struct.c -index ca639ed967b7..57f9817a9808 100644 ---- a/fs/fs_struct.c -+++ b/fs/fs_struct.c -@@ -46,6 +46,7 @@ void set_fs_pwd(struct fs_struct *fs, const struct path *path) - if (old_pwd.dentry) - path_put(&old_pwd); - } -+EXPORT_SYMBOL(set_fs_pwd); - - static inline int replace_path(struct path *p, const struct path *old, const struct path *new) - { -@@ -91,6 +92,7 @@ void free_fs_struct(struct fs_struct *fs) - path_put(&fs->pwd); - kmem_cache_free(fs_cachep, fs); - } -+EXPORT_SYMBOL(free_fs_struct); - - void exit_fs(struct task_struct *tsk) - { -@@ -129,6 +131,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) - } - return fs; - } -+EXPORT_SYMBOL_GPL(copy_fs_struct); - - int unshare_fs_struct(void) - { -diff --git a/fs/read_write.c b/fs/read_write.c -index 5bbf587f5bc1..45929fe56cfa 100644 ---- a/fs/read_write.c -+++ b/fs/read_write.c -@@ -469,6 +469,8 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) - return ret; - } - -+EXPORT_SYMBOL(vfs_read); -+ - static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) - { - struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; -@@ -566,6 +568,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ - - return ret; - } -+EXPORT_SYMBOL(vfs_write); - - /* file_ppos returns &file->f_pos or NULL if file is stream */ - static inline loff_t *file_ppos(struct file *file) -diff --git a/security/security.c b/security/security.c -index 1bc000f834e2..ab1a1a10c671 100644 ---- a/security/security.c -+++ b/security/security.c -@@ -1101,6 +1101,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) - return 0; - return call_int_hook(path_chown, 0, path, uid, gid); - } -+EXPORT_SYMBOL(security_path_chown); - - int security_path_chroot(const struct path *path) - { diff --git a/patches/ANDROID-sdcardfs-fix-fall-through-in-param-parsing.patch b/patches/ANDROID-sdcardfs-fix-fall-through-in-param-parsing.patch deleted file mode 100644 index 97551d203dd3c2b979720413a3c3518d5535ec6f..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sdcardfs-fix-fall-through-in-param-parsing.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Tue, 27 Aug 2019 16:20:38 -0700 -Subject: ANDROID: sdcardfs: fix fall through in param parsing - -Fixes: commit bafafd3663c2e ("ANDROID: sdcardfs: Add sdcardfs filesystem") -Change-Id: I936ac03b999095d46810c0ca55a7a29cab52d82a -Signed-off-by: Daniel Rosenberg ---- - fs/sdcardfs/main.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c -index b8e5cf2b9ae5..818122410bfe 100644 ---- a/fs/sdcardfs/main.c -+++ b/fs/sdcardfs/main.c -@@ -77,6 +77,7 @@ static int sdcardfs_parse_param(struct fs_context *fc, struct fs_parameter *para - switch (opt) { - case Opt_debug: - opts->debug = true; -+ break; - case Opt_fsuid: - opts->fs_low_uid = result.uint_32; - break; diff --git a/patches/ANDROID-security-perf-Allow-further-restriction-of-perf_event_open.patch b/patches/ANDROID-security-perf-Allow-further-restriction-of-perf_event_open.patch deleted file mode 100644 index e26f35e7f9af82fd0f6fa93d3381fd723d0ea862..0000000000000000000000000000000000000000 --- a/patches/ANDROID-security-perf-Allow-further-restriction-of-perf_event_open.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jeff Vander Stoep -Date: Sun, 29 May 2016 14:22:32 -0700 -Subject: ANDROID: security,perf: Allow further restriction of perf_event_open - -When kernel.perf_event_open is set to 3 (or greater), disallow all -access to performance events by users without CAP_SYS_ADMIN. -Add a Kconfig symbol CONFIG_SECURITY_PERF_EVENTS_RESTRICT that -makes this value the default. - -This is based on a similar feature in grsecurity -(CONFIG_GRKERNSEC_PERF_HARDEN). This version doesn't include making -the variable read-only. It also allows enabling further restriction -at run-time regardless of whether the default is changed. - -https://lkml.org/lkml/2016/1/11/587 - -Bug: 29054680 -Bug: 120445712 -Change-Id: Iff5bff4fc1042e85866df9faa01bce8d04335ab8 -[jeffv: Upstream doesn't want it https://lkml.org/lkml/2016/6/17/101] -Signed-off-by: Ben Hutchings ---- - Documentation/admin-guide/sysctl/kernel.rst | 5 ++++- - include/linux/perf_event.h | 5 +++++ - kernel/events/core.c | 8 ++++++++ - security/Kconfig | 9 +++++++++ - 4 files changed, 26 insertions(+), 1 deletion(-) - -diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst -index 032c7cd3cede..172fac5c58b1 100644 ---- a/Documentation/admin-guide/sysctl/kernel.rst -+++ b/Documentation/admin-guide/sysctl/kernel.rst -@@ -720,7 +720,8 @@ perf_event_paranoid: - ==================== - - Controls use of the performance events system by unprivileged --users (without CAP_SYS_ADMIN). The default value is 2. -+users (without CAP_SYS_ADMIN). The default value is 3 if -+CONFIG_SECURITY_PERF_EVENTS_RESTRICT is set, or 2 otherwise. - - === ================================================================== - -1 Allow use of (almost) all events by all users -@@ -734,6 +735,8 @@ users (without CAP_SYS_ADMIN). The default value is 2. - >=1 Disallow CPU event access by users without CAP_SYS_ADMIN - - >=2 Disallow kernel profiling by users without CAP_SYS_ADMIN -+ -+>=3: Disallow all event access by users without CAP_SYS_ADMIN - === ================================================================== - - -diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h -index 61448c19a132..a24e32410915 100644 ---- a/include/linux/perf_event.h -+++ b/include/linux/perf_event.h -@@ -1241,6 +1241,11 @@ extern int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, - int perf_event_max_stack_handler(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos); - -+static inline bool perf_paranoid_any(void) -+{ -+ return sysctl_perf_event_paranoid > 2; -+} -+ - static inline bool perf_paranoid_tracepoint_raw(void) - { - return sysctl_perf_event_paranoid > -1; -diff --git a/kernel/events/core.c b/kernel/events/core.c -index 9ec0b0bfddbd..db1cbe0b652d 100644 ---- a/kernel/events/core.c -+++ b/kernel/events/core.c -@@ -398,8 +398,13 @@ static cpumask_var_t perf_online_mask; - * 0 - disallow raw tracepoint access for unpriv - * 1 - disallow cpu events for unpriv - * 2 - disallow kernel profiling for unpriv -+ * 3 - disallow all unpriv perf event use - */ -+#ifdef CONFIG_SECURITY_PERF_EVENTS_RESTRICT -+int sysctl_perf_event_paranoid __read_mostly = 3; -+#else - int sysctl_perf_event_paranoid __read_mostly = 2; -+#endif - - /* Minimum for 512 kiB + 1 user control page */ - int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */ -@@ -10886,6 +10891,9 @@ SYSCALL_DEFINE5(perf_event_open, - if (flags & ~PERF_FLAG_ALL) - return -EINVAL; - -+ if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN)) -+ return -EACCES; -+ - err = perf_copy_attr(attr_uptr, &attr); - if (err) - return err; -diff --git a/security/Kconfig b/security/Kconfig -index 2a1a2d396228..c66f43a36dbe 100644 ---- a/security/Kconfig -+++ b/security/Kconfig -@@ -19,6 +19,15 @@ config SECURITY_DMESG_RESTRICT - - If you are unsure how to answer this question, answer N. - -+config SECURITY_PERF_EVENTS_RESTRICT -+ bool "Restrict unprivileged use of performance events" -+ depends on PERF_EVENTS -+ help -+ If you say Y here, the kernel.perf_event_paranoid sysctl -+ will be set to 3 by default, and no unprivileged use of the -+ perf_event_open syscall will be permitted unless it is -+ changed. -+ - config SECURITY - bool "Enable different security models" - depends on SYSFS diff --git a/patches/ANDROID-staging-android-ion-Decouple-ION-page-pooling-from-ION-core.patch b/patches/ANDROID-staging-android-ion-Decouple-ION-page-pooling-from-ION-core.patch deleted file mode 100644 index 6359a88e62784f028a42cc6565f4df83df22541b..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-android-ion-Decouple-ION-page-pooling-from-ION-core.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Isaac J. Manjarres" -Date: Wed, 19 Jun 2019 15:37:15 -0700 -Subject: ANDROID: staging: android: ion: Decouple ION page pooling from ION - core - -Since page pooling is compiled together with the system heap, -and it is the only user, page pooling should not be a part -of the ION core. Thus, separate it out as a library, and -give it its own interface. - -Bug: 133508579 -Test: ion-unit-tests -Change-Id: I95909d250fc37a401d9e23264cd27c78a2a74637 -Signed-off-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion.h | 51 -------------- - drivers/staging/android/ion/ion_page_pool.c | 2 +- - drivers/staging/android/ion/ion_page_pool.h | 66 +++++++++++++++++++ - drivers/staging/android/ion/ion_system_heap.c | 1 + - 4 files changed, 68 insertions(+), 52 deletions(-) - create mode 100644 drivers/staging/android/ion/ion_page_pool.h - -diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h -index 74914a266e25..6f9f7c365f38 100644 ---- a/drivers/staging/android/ion/ion.h -+++ b/drivers/staging/android/ion/ion.h -@@ -249,55 +249,4 @@ size_t ion_heap_freelist_shrink(struct ion_heap *heap, - */ - size_t ion_heap_freelist_size(struct ion_heap *heap); - --/** -- * functions for creating and destroying a heap pool -- allows you -- * to keep a pool of pre allocated memory to use from your heap. Keeping -- * a pool of memory that is ready for dma, ie any cached mapping have been -- * invalidated from the cache, provides a significant performance benefit on -- * many systems -- */ -- --/** -- * struct ion_page_pool - pagepool struct -- * @high_count: number of highmem items in the pool -- * @low_count: number of lowmem items in the pool -- * @high_items: list of highmem items -- * @low_items: list of lowmem items -- * @mutex: lock protecting this struct and especially the count -- * item list -- * @gfp_mask: gfp_mask to use from alloc -- * @order: order of pages in the pool -- * @list: plist node for list of pools -- * -- * Allows you to keep a pool of pre allocated pages to use from your heap. -- * Keeping a pool of pages that is ready for dma, ie any cached mapping have -- * been invalidated from the cache, provides a significant performance benefit -- * on many systems -- */ --struct ion_page_pool { -- int high_count; -- int low_count; -- struct list_head high_items; -- struct list_head low_items; -- struct mutex mutex; -- gfp_t gfp_mask; -- unsigned int order; -- struct plist_node list; --}; -- --struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); --void ion_page_pool_destroy(struct ion_page_pool *pool); --struct page *ion_page_pool_alloc(struct ion_page_pool *pool); --void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); -- --/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool -- * @pool: the pool -- * @gfp_mask: the memory type to reclaim -- * @nr_to_scan: number of items to shrink in pages -- * -- * returns the number of items freed in pages -- */ --int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, -- int nr_to_scan); -- - #endif /* _ION_H */ -diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c -index f85ec5b16b65..f1bc165e644e 100644 ---- a/drivers/staging/android/ion/ion_page_pool.c -+++ b/drivers/staging/android/ion/ion_page_pool.c -@@ -10,7 +10,7 @@ - #include - #include - --#include "ion.h" -+#include "ion_page_pool.h" - - static inline struct page *ion_page_pool_alloc_pages(struct ion_page_pool *pool) - { -diff --git a/drivers/staging/android/ion/ion_page_pool.h b/drivers/staging/android/ion/ion_page_pool.h -new file mode 100644 -index 000000000000..e205d0086833 ---- /dev/null -+++ b/drivers/staging/android/ion/ion_page_pool.h -@@ -0,0 +1,66 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * ION Page Pool kernel interface header -+ * -+ * Copyright (C) 2011 Google, Inc. -+ */ -+ -+#ifndef _ION_PAGE_POOL_H -+#define _ION_PAGE_POOL_H -+ -+#include -+#include -+#include -+#include -+ -+/** -+ * functions for creating and destroying a heap pool -- allows you -+ * to keep a pool of pre allocated memory to use from your heap. Keeping -+ * a pool of memory that is ready for dma, ie any cached mapping have been -+ * invalidated from the cache, provides a significant performance benefit on -+ * many systems -+ */ -+ -+/** -+ * struct ion_page_pool - pagepool struct -+ * @high_count: number of highmem items in the pool -+ * @low_count: number of lowmem items in the pool -+ * @high_items: list of highmem items -+ * @low_items: list of lowmem items -+ * @mutex: lock protecting this struct and especially the count -+ * item list -+ * @gfp_mask: gfp_mask to use from alloc -+ * @order: order of pages in the pool -+ * @list: plist node for list of pools -+ * -+ * Allows you to keep a pool of pre allocated pages to use from your heap. -+ * Keeping a pool of pages that is ready for dma, ie any cached mapping have -+ * been invalidated from the cache, provides a significant performance benefit -+ * on many systems -+ */ -+struct ion_page_pool { -+ int high_count; -+ int low_count; -+ struct list_head high_items; -+ struct list_head low_items; -+ struct mutex mutex; -+ gfp_t gfp_mask; -+ unsigned int order; -+ struct plist_node list; -+}; -+ -+struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); -+void ion_page_pool_destroy(struct ion_page_pool *pool); -+struct page *ion_page_pool_alloc(struct ion_page_pool *pool); -+void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); -+ -+/** ion_page_pool_shrink - shrinks the size of the memory cached in the pool -+ * @pool: the pool -+ * @gfp_mask: the memory type to reclaim -+ * @nr_to_scan: number of items to shrink in pages -+ * -+ * returns the number of items freed in pages -+ */ -+int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, -+ int nr_to_scan); -+#endif /* _ION_PAGE_POOL_H */ -diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c -index b83a1d16bd89..ee301df7b7b7 100644 ---- a/drivers/staging/android/ion/ion_system_heap.c -+++ b/drivers/staging/android/ion/ion_system_heap.c -@@ -15,6 +15,7 @@ - #include - - #include "ion.h" -+#include "ion_page_pool.h" - - #define NUM_ORDERS ARRAY_SIZE(orders) - diff --git a/patches/ANDROID-staging-android-ion-Expose-ion_alloc-to-kernel-space.patch b/patches/ANDROID-staging-android-ion-Expose-ion_alloc-to-kernel-space.patch deleted file mode 100644 index 6d922c9f0f208f6e1a9b277d41c082750987f7da..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-android-ion-Expose-ion_alloc-to-kernel-space.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Isaac J. Manjarres" -Date: Wed, 19 Jun 2019 15:37:14 -0700 -Subject: ANDROID: staging: android: ion: Expose ion_alloc() to kernel space - -Expose ion_alloc() to kernel space clients. Users of this -function will receive a dma-buf structure for sharing -the ION buffer that was allocated. - -Bug: 133508579 -Test: ion-unit-tests -Change-Id: I410044127ba92a759a79c65e422b0b75b74e2159 -Signed-off-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion.c | 40 +++++++++++++++++++++++-------- - include/linux/ion.h | 26 ++++++++++++++++++++ - 2 files changed, 56 insertions(+), 10 deletions(-) - create mode 100644 include/linux/ion.h - -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index e6b1ca141b93..2e5c6ae2f3fc 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -3,6 +3,8 @@ - * ION Memory Allocator - * - * Copyright (C) 2011 Google, Inc. -+ * Copyright (c) 2019, The Linux Foundation. All rights reserved. -+ * - */ - - #include -@@ -353,13 +355,13 @@ static const struct dma_buf_ops dma_buf_ops = { - .unmap = ion_dma_buf_kunmap, - }; - --static int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) -+static struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask, -+ unsigned int flags) - { - struct ion_device *dev = internal_dev; - struct ion_buffer *buffer = NULL; - struct ion_heap *heap; - DEFINE_DMA_BUF_EXPORT_INFO(exp_info); -- int fd; - struct dma_buf *dmabuf; - - pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, -@@ -373,7 +375,7 @@ static int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) - len = PAGE_ALIGN(len); - - if (!len) -- return -EINVAL; -+ return ERR_PTR(-EINVAL); - - down_read(&dev->lock); - plist_for_each_entry(heap, &dev->heaps, node) { -@@ -387,10 +389,10 @@ static int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) - up_read(&dev->lock); - - if (!buffer) -- return -ENODEV; -+ return ERR_PTR(-ENODEV); - - if (IS_ERR(buffer)) -- return PTR_ERR(buffer); -+ return ERR_CAST(buffer); - - exp_info.ops = &dma_buf_ops; - exp_info.size = buffer->size; -@@ -398,10 +400,28 @@ static int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) - exp_info.priv = buffer; - - dmabuf = dma_buf_export(&exp_info); -- if (IS_ERR(dmabuf)) { -+ if (IS_ERR(dmabuf)) - _ion_buffer_destroy(buffer); -+ -+ return dmabuf; -+} -+ -+struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, -+ unsigned int flags) -+{ -+ return ion_alloc_dmabuf(len, heap_id_mask, flags); -+} -+EXPORT_SYMBOL_GPL(ion_alloc); -+ -+static int ion_alloc_fd(size_t len, unsigned int heap_id_mask, -+ unsigned int flags) -+{ -+ int fd; -+ struct dma_buf *dmabuf; -+ -+ dmabuf = ion_alloc_dmabuf(len, heap_id_mask, flags); -+ if (IS_ERR(dmabuf)) - return PTR_ERR(dmabuf); -- } - - fd = dma_buf_fd(dmabuf, O_CLOEXEC); - if (fd < 0) -@@ -506,9 +526,9 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - { - int fd; - -- fd = ion_alloc(data.allocation.len, -- data.allocation.heap_id_mask, -- data.allocation.flags); -+ fd = ion_alloc_fd(data.allocation.len, -+ data.allocation.heap_id_mask, -+ data.allocation.flags); - if (fd < 0) - return fd; - -diff --git a/include/linux/ion.h b/include/linux/ion.h -new file mode 100644 -index 000000000000..7bec77d98224 ---- /dev/null -+++ b/include/linux/ion.h -@@ -0,0 +1,26 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (c) 2019, The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef _ION_KERNEL_H -+#define _ION_KERNEL_H -+ -+#include -+#include -+ -+#ifdef CONFIG_ION -+/* -+ * Allocates an ION buffer. -+ */ -+struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, -+ unsigned int flags); -+ -+#else -+static inline struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, -+ unsigned int flags) -+{ -+ return ERR_PTR(-ENOMEM); -+} -+#endif /* CONFIG_ION */ -+#endif /* _ION_KERNEL_H */ diff --git a/patches/ANDROID-staging-ion-Add-support-for-heap-specific-dma_buf_ops.patch b/patches/ANDROID-staging-ion-Add-support-for-heap-specific-dma_buf_ops.patch deleted file mode 100644 index 776750716d20667615f6283b4f3f3ea1e87d76a9..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-Add-support-for-heap-specific-dma_buf_ops.patch +++ /dev/null @@ -1,331 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Sun, 1 Sep 2019 22:38:52 -0700 -Subject: ANDROID: staging: ion: Add support for heap-specific dma_buf_ops - -All dma_buf ops are registered by ion core. However, if a given heap -provides a specific dmabuf operation, that will be preferred over the -default ion core implementation - -Some dma_buf_ops like get_flags, begin_cpu_access_partial etc are -entirely not supported by ion core and will return -EOPNOTSUPP if the -heap implementation doesn't provided the necessary overrides. - -Tested with ion unit test with default system heap. - -Bug: 133508579 -Bug: 140290587 -Test: ion-unit-test - -Change-Id: Id13c5c280064b6f47de327223733c2c393f1a41a -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion_dma_buf.c | 207 +++++++++++++++++----- - include/linux/ion.h | 2 + - 2 files changed, 163 insertions(+), 46 deletions(-) - -diff --git a/drivers/staging/android/ion/ion_dma_buf.c b/drivers/staging/android/ion/ion_dma_buf.c -index 0de08e6f1af5..e52db6a182ae 100644 ---- a/drivers/staging/android/ion/ion_dma_buf.c -+++ b/drivers/staging/android/ion/ion_dma_buf.c -@@ -6,7 +6,6 @@ - */ - - #include --#include - #include - #include - #include -@@ -96,80 +95,68 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf, - kfree(a); - } - --static struct sg_table *ion_dma_buf_map(struct dma_buf_attachment *attachment, -+static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, - enum dma_data_direction direction) - { -- struct ion_dma_buf_attachment *a = attachment->priv; -+ struct ion_buffer *buffer = attachment->dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ struct ion_dma_buf_attachment *a; - struct sg_table *table; - -+ if (heap->buf_ops.map_dma_buf) -+ return heap->buf_ops.map_dma_buf(attachment, direction); -+ -+ a = attachment->priv; - table = a->table; - -- if (!dma_map_sg(attachment->dev, table->sgl, table->nents, -- direction)) -+ if (!dma_map_sg(attachment->dev, table->sgl, table->nents, direction)) - return ERR_PTR(-ENOMEM); - - return table; - } - --static void ion_dma_buf_unmap(struct dma_buf_attachment *attachment, -+static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, - struct sg_table *table, - enum dma_data_direction direction) - { -- dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction); --} -- --static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) --{ -- struct ion_buffer *buffer = dmabuf->priv; -- int ret = 0; -+ struct ion_buffer *buffer = attachment->dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; - -- if (!buffer->heap->ops->map_user) { -- pr_err("%s: this heap does not define a method for mapping to userspace\n", -- __func__); -- return -EINVAL; -- } -- -- if (!(buffer->flags & ION_FLAG_CACHED)) -- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ if (heap->buf_ops.unmap_dma_buf) -+ return heap->buf_ops.unmap_dma_buf(attachment, table, -+ direction); - -- mutex_lock(&buffer->lock); -- /* now map it to userspace */ -- ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); -- mutex_unlock(&buffer->lock); -- -- if (ret) -- pr_err("%s: failure mapping buffer to userspace\n", -- __func__); -- -- return ret; -+ dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction); - } - - static void ion_dma_buf_release(struct dma_buf *dmabuf) - { - struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; - -- ion_free(buffer); --} -- --static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) --{ -- struct ion_buffer *buffer = dmabuf->priv; -+ if (heap->buf_ops.release) -+ return heap->buf_ops.release(dmabuf); - -- return buffer->vaddr + offset * PAGE_SIZE; -+ ion_free(buffer); - } - - static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction direction) - { - struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; - void *vaddr; - struct ion_dma_buf_attachment *a; -- int ret = 0; -+ int ret; -+ -+ if (heap->buf_ops.begin_cpu_access) -+ return heap->buf_ops.begin_cpu_access(dmabuf, direction); - - /* - * TODO: Move this elsewhere because we don't always need a vaddr - */ -- if (buffer->heap->ops->map_kernel) { -+ ret = 0; -+ if (heap->ops->map_kernel) { - mutex_lock(&buffer->lock); - vaddr = ion_buffer_kmap_get(buffer); - if (IS_ERR(vaddr)) { -@@ -190,13 +177,36 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - return ret; - } - -+static int -+ion_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, -+ enum dma_data_direction direction, -+ unsigned int offset, unsigned int len) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ -+ /* This is done to make sure partial buffer cache flush / invalidate is -+ * allowed. The implementation may be vendor specific in this case, so -+ * ion core does not provide a default implementation -+ */ -+ if (!heap->buf_ops.begin_cpu_access_partial) -+ return -EOPNOTSUPP; -+ -+ return heap->buf_ops.begin_cpu_access_partial(dmabuf, direction, offset, -+ len); -+} -+ - static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction direction) - { - struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; - struct ion_dma_buf_attachment *a; - -- if (buffer->heap->ops->map_kernel) { -+ if (heap->buf_ops.end_cpu_access) -+ return heap->buf_ops.end_cpu_access(dmabuf, direction); -+ -+ if (heap->ops->map_kernel) { - mutex_lock(&buffer->lock); - ion_buffer_kmap_put(buffer); - mutex_unlock(&buffer->lock); -@@ -212,16 +222,121 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, - return 0; - } - -+static int ion_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, -+ enum dma_data_direction direction, -+ unsigned int offset, -+ unsigned int len) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ -+ /* This is done to make sure partial buffer cache flush / invalidate is -+ * allowed. The implementation may be vendor specific in this case, so -+ * ion core does not provide a default implementation -+ */ -+ if (!heap->buf_ops.end_cpu_access_partial) -+ return -EOPNOTSUPP; -+ -+ return heap->buf_ops.end_cpu_access_partial(dmabuf, direction, offset, -+ len); -+} -+ -+static void *ion_dma_buf_map(struct dma_buf *dmabuf, unsigned long offset) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ -+ if (heap->buf_ops.map) -+ return heap->buf_ops.map(dmabuf, offset); -+ -+ return buffer->vaddr + offset * PAGE_SIZE; -+} -+ -+static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ int ret; -+ -+ /* now map it to userspace */ -+ if (heap->buf_ops.mmap) { -+ ret = heap->buf_ops.mmap(dmabuf, vma); -+ } else { -+ mutex_lock(&buffer->lock); -+ if (!(buffer->flags & ION_FLAG_CACHED)) -+ vma->vm_page_prot = -+ pgprot_writecombine(vma->vm_page_prot); -+ -+ ret = ion_heap_map_user(heap, buffer, vma); -+ mutex_unlock(&buffer->lock); -+ } -+ -+ if (ret) -+ pr_err("%s: failure mapping buffer to userspace\n", __func__); -+ -+ return ret; -+} -+ -+static void ion_dma_buf_unmap(struct dma_buf *dmabuf, unsigned long offset, -+ void *addr) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ -+ if (!heap->buf_ops.unmap) -+ return; -+ heap->buf_ops.unmap(dmabuf, offset, addr); -+} -+ -+static void *ion_dma_buf_vmap(struct dma_buf *dmabuf) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ -+ if (!heap->buf_ops.vmap) -+ return ERR_PTR(-EOPNOTSUPP); -+ -+ return heap->buf_ops.vmap(dmabuf); -+} -+ -+static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ -+ if (!heap->buf_ops.vunmap) -+ return; -+ -+ return heap->buf_ops.vunmap(dmabuf, vaddr); -+} -+ -+static int ion_dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_heap *heap = buffer->heap; -+ -+ if (!heap->buf_ops.get_flags) -+ return -EOPNOTSUPP; -+ -+ return heap->buf_ops.get_flags(dmabuf, flags); -+} -+ - static const struct dma_buf_ops dma_buf_ops = { -- .map_dma_buf = ion_dma_buf_map, -- .unmap_dma_buf = ion_dma_buf_unmap, -- .mmap = ion_dma_buf_mmap, -- .release = ion_dma_buf_release, - .attach = ion_dma_buf_attach, - .detach = ion_dma_buf_detatch, -+ .map_dma_buf = ion_map_dma_buf, -+ .unmap_dma_buf = ion_unmap_dma_buf, -+ .release = ion_dma_buf_release, - .begin_cpu_access = ion_dma_buf_begin_cpu_access, -+ .begin_cpu_access_partial = ion_dma_buf_begin_cpu_access_partial, - .end_cpu_access = ion_dma_buf_end_cpu_access, -- .map = ion_dma_buf_kmap, -+ .end_cpu_access_partial = ion_dma_buf_end_cpu_access_partial, -+ .mmap = ion_dma_buf_mmap, -+ .map = ion_dma_buf_map, -+ .unmap = ion_dma_buf_unmap, -+ .vmap = ion_dma_buf_vmap, -+ .vunmap = ion_dma_buf_vunmap, -+ .get_flags = ion_dma_buf_get_flags, - }; - - struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, -diff --git a/include/linux/ion.h b/include/linux/ion.h -index 5d68674b015a..1e4846db0c6d 100644 ---- a/include/linux/ion.h -+++ b/include/linux/ion.h -@@ -101,6 +101,7 @@ struct ion_heap_ops { - * @node: rb node to put the heap on the device's tree of heaps - * @type: type of heap - * @ops: ops struct as above -+ * @buf_ops: dma_buf ops specific to the heap implementation. - * @flags: flags - * @id: id of heap, also indicates priority of this heap when - * allocating. These are specified by platform data and -@@ -126,6 +127,7 @@ struct ion_heap { - struct plist_node node; - enum ion_heap_type type; - struct ion_heap_ops *ops; -+ struct dma_buf_ops buf_ops; - unsigned long flags; - unsigned int id; - const char *name; diff --git a/patches/ANDROID-staging-ion-Build-fix-for-mips.patch b/patches/ANDROID-staging-ion-Build-fix-for-mips.patch deleted file mode 100644 index 3f51840c86edfdd0c69952f6f2a0aba242ea36dd..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-Build-fix-for-mips.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Delva -Date: Mon, 19 Aug 2019 18:27:29 -0700 -Subject: ANDROID: staging: ion: Build fix for mips - -Bug: 133508579 -Change-Id: Ie795483ace50537029921d86347f38bd1e5ee58a -Signed-off-by: Alistair Delva ---- - drivers/staging/android/ion/ion_buffer.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c -index 879b3ddb08c0..961605a35c59 100644 ---- a/drivers/staging/android/ion/ion_buffer.c -+++ b/drivers/staging/android/ion/ion_buffer.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - #include "ion_private.h" - diff --git a/patches/ANDROID-staging-ion-Fix-uninitialized-variable-warning.patch b/patches/ANDROID-staging-ion-Fix-uninitialized-variable-warning.patch deleted file mode 100644 index c6e15e5dfcaa335af6b51a9774f189f20ac503f4..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-Fix-uninitialized-variable-warning.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Fri, 30 Aug 2019 14:46:57 -0700 -Subject: ANDROID: staging: ion: Fix uninitialized variable warning - -Warning: - In file included from include/linux/bitops.h:19:0, - from include/linux/bitmap.h:8, - from drivers/staging/android/ion/ion.c:10: - drivers/staging/android/ion/ion.c: In function '__ion_device_add_heap': ->> arch/m68k/include/asm/bitops.h:371:28: warning: 'end_bit' may be used uninitialized in this function [-Wmaybe-uninitialized] - #define find_next_zero_bit find_next_zero_bit - ^~~~~~~~~~~~~~~~~~ - drivers/staging/android/ion/ion.c:228:17: note: 'end_bit' was declared here - int start_bit, end_bit; - ^~~~~~~ - In file included from include/linux/bitops.h:19:0, - from include/linux/bitmap.h:8, - from drivers/staging/android/ion/ion.c:10: ->> arch/m68k/include/asm/bitops.h:354:10: warning: 'start_bit' may be used uninitialized in this function [-Wmaybe-uninitialized] - offset -= bit; - ~~~~~~~^~~~~~ - drivers/staging/android/ion/ion.c:228:6: note: 'start_bit' was declared here - int start_bit, end_bit; - ^~~~~~~~~ - -Change-Id: I2df4a5b36f457aca5f19c03976ae7229c35ecdb3 -Reported-by: kbuild test robot -Fixes: acbfdf321afb ("ANDROID: staging: ion: add support for consistent heap ids") -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index c7be7457a709..c8ed051715bc 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -225,7 +225,7 @@ DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, - static int ion_assign_heap_id(struct ion_heap *heap, struct ion_device *dev) - { - int id_bit; -- int start_bit, end_bit; -+ int start_bit, end_bit = -1; - - switch (heap->type) { - case ION_HEAP_TYPE_SYSTEM: diff --git a/patches/ANDROID-staging-ion-Move-ion-heaps-into-their-own-directory.patch b/patches/ANDROID-staging-ion-Move-ion-heaps-into-their-own-directory.patch deleted file mode 100644 index a4f3e0d0556b43b1f18747f925ec04d01424ef10..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-Move-ion-heaps-into-their-own-directory.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Thu, 8 Aug 2019 08:00:53 -0700 -Subject: ANDROID: staging: ion: Move ion heaps into their own directory - -This is preparatory work for ION heaps to be kernel modules, so -they stay in their own directory inside ION. The heap modules are -planned to be *overridable*, so it makes sense to isolate them -in source to explicitly draw the line between what is a kernel API. - -Bug: 133508579 -Test: ion-unit-tests - -Change-Id: Iefc4e22d186139832f54b9cfc629383fb6698fc6 -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/Kconfig | 15 +-------------- - drivers/staging/android/ion/Makefile | 5 ++--- - drivers/staging/android/ion/heaps/Kconfig | 15 +++++++++++++++ - drivers/staging/android/ion/heaps/Makefile | 3 +++ - .../android/ion/{ => heaps}/ion_cma_heap.c | 2 +- - .../android/ion/{ => heaps}/ion_page_pool.c | 0 - .../android/ion/{ => heaps}/ion_page_pool.h | 0 - .../android/ion/{ => heaps}/ion_system_heap.c | 2 +- - 8 files changed, 23 insertions(+), 19 deletions(-) - create mode 100644 drivers/staging/android/ion/heaps/Kconfig - create mode 100644 drivers/staging/android/ion/heaps/Makefile - rename drivers/staging/android/ion/{ => heaps}/ion_cma_heap.c (99%) - rename drivers/staging/android/ion/{ => heaps}/ion_page_pool.c (100%) - rename drivers/staging/android/ion/{ => heaps}/ion_page_pool.h (100%) - rename drivers/staging/android/ion/{ => heaps}/ion_system_heap.c (99%) - -diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig -index 989fe84a9f9d..7b7da979991e 100644 ---- a/drivers/staging/android/ion/Kconfig -+++ b/drivers/staging/android/ion/Kconfig -@@ -11,17 +11,4 @@ menuconfig ION - If you're not using Android its probably safe to - say N here. - --config ION_SYSTEM_HEAP -- bool "Ion system heap" -- depends on ION -- help -- Choose this option to enable the Ion system heap. The system heap -- is backed by pages from the buddy allocator. If in doubt, say Y. -- --config ION_CMA_HEAP -- bool "Ion CMA heap support" -- depends on ION && DMA_CMA -- help -- Choose this option to enable CMA heaps with Ion. This heap is backed -- by the Contiguous Memory Allocator (CMA). If your system has these -- regions, you should say Y here. -+source "drivers/staging/android/ion/heaps/Kconfig" -diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile -index b6fab2816781..1f7704e02fb0 100644 ---- a/drivers/staging/android/ion/Makefile -+++ b/drivers/staging/android/ion/Makefile -@@ -1,4 +1,3 @@ - # SPDX-License-Identifier: GPL-2.0 --obj-$(CONFIG_ION) += ion.o ion_buffer.o ion_dma_buf.o ion_heap.o --obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o --obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -+obj-$(CONFIG_ION) += ion.o ion_buffer.o ion_dma_buf.o ion_heap.o -+obj-y += heaps/ -diff --git a/drivers/staging/android/ion/heaps/Kconfig b/drivers/staging/android/ion/heaps/Kconfig -new file mode 100644 -index 000000000000..7affa91ecabb ---- /dev/null -+++ b/drivers/staging/android/ion/heaps/Kconfig -@@ -0,0 +1,15 @@ -+# SPDX-License-Identifier: GPL-2.0 -+config ION_SYSTEM_HEAP -+ bool "Ion system heap" -+ depends on ION -+ help -+ Choose this option to enable the Ion system heap. The system heap -+ is backed by pages from the buddy allocator. If in doubt, say Y. -+ -+config ION_CMA_HEAP -+ bool "Ion CMA heap support" -+ depends on ION && DMA_CMA -+ help -+ Choose this option to enable CMA heaps with Ion. This heap is backed -+ by the Contiguous Memory Allocator (CMA). If your system has these -+ regions, you should say Y here. -diff --git a/drivers/staging/android/ion/heaps/Makefile b/drivers/staging/android/ion/heaps/Makefile -new file mode 100644 -index 000000000000..127912629f0b ---- /dev/null -+++ b/drivers/staging/android/ion/heaps/Makefile -@@ -0,0 +1,3 @@ -+# SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o -+obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/heaps/ion_cma_heap.c -similarity index 99% -rename from drivers/staging/android/ion/ion_cma_heap.c -rename to drivers/staging/android/ion/heaps/ion_cma_heap.c -index bf65e67ef9d8..0872e5d630f8 100644 ---- a/drivers/staging/android/ion/ion_cma_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_cma_heap.c -@@ -14,7 +14,7 @@ - #include - #include - --#include "ion.h" -+#include "../ion.h" - - struct ion_cma_heap { - struct ion_heap heap; -diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/heaps/ion_page_pool.c -similarity index 100% -rename from drivers/staging/android/ion/ion_page_pool.c -rename to drivers/staging/android/ion/heaps/ion_page_pool.c -diff --git a/drivers/staging/android/ion/ion_page_pool.h b/drivers/staging/android/ion/heaps/ion_page_pool.h -similarity index 100% -rename from drivers/staging/android/ion/ion_page_pool.h -rename to drivers/staging/android/ion/heaps/ion_page_pool.h -diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/heaps/ion_system_heap.c -similarity index 99% -rename from drivers/staging/android/ion/ion_system_heap.c -rename to drivers/staging/android/ion/heaps/ion_system_heap.c -index d1cb9e69399e..8e26016082d4 100644 ---- a/drivers/staging/android/ion/ion_system_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_heap.c -@@ -14,7 +14,7 @@ - #include - #include - --#include "ion.h" -+#include "../ion.h" - #include "ion_page_pool.h" - - #define NUM_ORDERS ARRAY_SIZE(orders) diff --git a/patches/ANDROID-staging-ion-Remove-unnecessary-ion-heap-ops.patch b/patches/ANDROID-staging-ion-Remove-unnecessary-ion-heap-ops.patch deleted file mode 100644 index 96c805e0a3b7c0f360d3513c797fee95d2b42cac..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-Remove-unnecessary-ion-heap-ops.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Sun, 1 Sep 2019 23:02:37 -0700 -Subject: ANDROID: staging: ion: Remove unnecessary ion heap ops - -The heap operations are redundant now that we have default -dma_buf operations. So, remove them. - -Bug: 133508579 -Bug: 140290587 -Test: ion-unit-tests - -Change-Id: I8f87c22896e128f48ed222421cabc23ab238ff69 -Signed-off-by: Sandeep Patil ---- - .../staging/android/ion/heaps/ion_cma_heap.c | 3 --- - .../ion/heaps/ion_system_contig_heap.c | 3 --- - .../android/ion/heaps/ion_system_heap.c | 3 --- - drivers/staging/android/ion/ion_buffer.c | 6 ++--- - drivers/staging/android/ion/ion_dma_buf.c | 25 +++++++------------ - include/linux/ion.h | 9 +------ - 6 files changed, 13 insertions(+), 36 deletions(-) - -diff --git a/drivers/staging/android/ion/heaps/ion_cma_heap.c b/drivers/staging/android/ion/heaps/ion_cma_heap.c -index 83f7dce74f18..236b6c576cdb 100644 ---- a/drivers/staging/android/ion/heaps/ion_cma_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_cma_heap.c -@@ -95,9 +95,6 @@ static void ion_cma_free(struct ion_buffer *buffer) - static struct ion_heap_ops ion_cma_ops = { - .allocate = ion_cma_allocate, - .free = ion_cma_free, -- .map_user = ion_heap_map_user, -- .map_kernel = ion_heap_map_kernel, -- .unmap_kernel = ion_heap_unmap_kernel, - }; - - static struct ion_heap *__ion_cma_heap_create(struct cma *cma) -diff --git a/drivers/staging/android/ion/heaps/ion_system_contig_heap.c b/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -index 9cb18e38dc96..36e8769f3ef7 100644 ---- a/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -@@ -77,9 +77,6 @@ static void ion_system_contig_heap_free(struct ion_buffer *buffer) - static struct ion_heap_ops kmalloc_ops = { - .allocate = ion_system_contig_heap_allocate, - .free = ion_system_contig_heap_free, -- .map_kernel = ion_heap_map_kernel, -- .unmap_kernel = ion_heap_unmap_kernel, -- .map_user = ion_heap_map_user, - }; - - static struct ion_heap contig_heap = { -diff --git a/drivers/staging/android/ion/heaps/ion_system_heap.c b/drivers/staging/android/ion/heaps/ion_system_heap.c -index 3aed952c219d..792cd130e493 100644 ---- a/drivers/staging/android/ion/heaps/ion_system_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_heap.c -@@ -241,9 +241,6 @@ static int ion_system_heap_create_pools(struct ion_page_pool **pools) - static struct ion_heap_ops system_heap_ops = { - .allocate = ion_system_heap_allocate, - .free = ion_system_heap_free, -- .map_kernel = ion_heap_map_kernel, -- .unmap_kernel = ion_heap_unmap_kernel, -- .map_user = ion_heap_map_user, - .shrink = ion_system_heap_shrink, - }; - -diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c -index 961605a35c59..4157f5d040f2 100644 ---- a/drivers/staging/android/ion/ion_buffer.c -+++ b/drivers/staging/android/ion/ion_buffer.c -@@ -201,7 +201,7 @@ void ion_buffer_release(struct ion_buffer *buffer) - if (buffer->kmap_cnt > 0) { - pr_warn_once("%s: buffer still mapped in the kernel\n", - __func__); -- buffer->heap->ops->unmap_kernel(buffer->heap, buffer); -+ ion_heap_unmap_kernel(buffer->heap, buffer); - } - buffer->heap->ops->free(buffer); - spin_lock(&buffer->heap->stat_lock); -@@ -245,7 +245,7 @@ void *ion_buffer_kmap_get(struct ion_buffer *buffer) - buffer->kmap_cnt++; - return buffer->vaddr; - } -- vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); -+ vaddr = ion_heap_map_kernel(buffer->heap, buffer); - if (WARN_ONCE(!vaddr, - "heap->ops->map_kernel should return ERR_PTR on error")) - return ERR_PTR(-EINVAL); -@@ -260,7 +260,7 @@ void ion_buffer_kmap_put(struct ion_buffer *buffer) - { - buffer->kmap_cnt--; - if (!buffer->kmap_cnt) { -- buffer->heap->ops->unmap_kernel(buffer->heap, buffer); -+ ion_heap_unmap_kernel(buffer->heap, buffer); - buffer->vaddr = NULL; - } - } -diff --git a/drivers/staging/android/ion/ion_dma_buf.c b/drivers/staging/android/ion/ion_dma_buf.c -index e52db6a182ae..7ded926f52d4 100644 ---- a/drivers/staging/android/ion/ion_dma_buf.c -+++ b/drivers/staging/android/ion/ion_dma_buf.c -@@ -154,19 +154,16 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - - /* - * TODO: Move this elsewhere because we don't always need a vaddr -+ * FIXME: Why do we need a vaddr here? - */ - ret = 0; -- if (heap->ops->map_kernel) { -- mutex_lock(&buffer->lock); -- vaddr = ion_buffer_kmap_get(buffer); -- if (IS_ERR(vaddr)) { -- ret = PTR_ERR(vaddr); -- goto unlock; -- } -- mutex_unlock(&buffer->lock); -+ mutex_lock(&buffer->lock); -+ vaddr = ion_buffer_kmap_get(buffer); -+ if (IS_ERR(vaddr)) { -+ ret = PTR_ERR(vaddr); -+ goto unlock; - } - -- mutex_lock(&buffer->lock); - list_for_each_entry(a, &buffer->attachments, list) { - dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents, - direction); -@@ -206,13 +203,9 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, - if (heap->buf_ops.end_cpu_access) - return heap->buf_ops.end_cpu_access(dmabuf, direction); - -- if (heap->ops->map_kernel) { -- mutex_lock(&buffer->lock); -- ion_buffer_kmap_put(buffer); -- mutex_unlock(&buffer->lock); -- } -- - mutex_lock(&buffer->lock); -+ -+ ion_buffer_kmap_put(buffer); - list_for_each_entry(a, &buffer->attachments, list) { - dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents, - direction); -@@ -249,7 +242,7 @@ static void *ion_dma_buf_map(struct dma_buf *dmabuf, unsigned long offset) - if (heap->buf_ops.map) - return heap->buf_ops.map(dmabuf, offset); - -- return buffer->vaddr + offset * PAGE_SIZE; -+ return ion_buffer_kmap_get(buffer) + offset * PAGE_SIZE; - } - - static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) -diff --git a/include/linux/ion.h b/include/linux/ion.h -index 1e4846db0c6d..87aa2bcec7d3 100644 ---- a/include/linux/ion.h -+++ b/include/linux/ion.h -@@ -57,11 +57,8 @@ struct ion_buffer { - * struct ion_heap_ops - ops to operate on a given heap - * @allocate: allocate memory - * @free: free memory -- * @map_kernel map memory to the kernel -- * @unmap_kernel unmap memory to the kernel -- * @map_user map memory to userspace - * -- * allocate, phys, and map_user return 0 on success, -errno on error. -+ * allocate returns 0 on success, -errno on error. - * map_dma and map_kernel return pointer on success, ERR_PTR on - * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in - * the buffer's private_flags when called from a shrinker. In that -@@ -73,10 +70,6 @@ struct ion_heap_ops { - struct ion_buffer *buffer, unsigned long len, - unsigned long flags); - void (*free)(struct ion_buffer *buffer); -- void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); -- void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); -- int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, -- struct vm_area_struct *vma); - int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); - }; - diff --git a/patches/ANDROID-staging-ion-add-support-for-consistent-heap-ids.patch b/patches/ANDROID-staging-ion-add-support-for-consistent-heap-ids.patch deleted file mode 100644 index 795e979747676ff1f6019bc05c02f55cd3604f16..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-add-support-for-consistent-heap-ids.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Mon, 26 Aug 2019 22:46:07 -0700 -Subject: ANDROID: staging: ion: add support for consistent heap ids - -heap id is part of ION's UAPI. Since the heaps are now kernel modules, -the current scheme of incrementing the heap id for the next heap doesn't -work. For example, if one insert->remove->insert the system heap module, -the heap id associated with the system heap changes. This immediately -breaks all of userspace. - -So, in order to fix this, we reserve first 16 heap ids for GKI heaps -and leave 16 more heap ids for any custom heap type that may exist. - -Bug: 133508579 -Test: ion-unit-test -Test: ion-unit-test (after removal and insertion of system heap module) - -Change-Id: I8412e590263869e029151a017b072399f54206f0 -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion.c | 79 ++++++++++++++++++++++- - drivers/staging/android/ion/ion_private.h | 5 +- - 2 files changed, 80 insertions(+), 4 deletions(-) - -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index 548d65dbd3ac..c7be7457a709 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -7,6 +7,7 @@ - * - */ - -+#include - #include - #include - #include -@@ -27,7 +28,6 @@ - #include "ion_private.h" - - static struct ion_device *internal_dev; --static int heap_id; - - /* Entry into ION allocator for rest of the kernel */ - struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, -@@ -222,6 +222,69 @@ static int debug_shrink_get(void *data, u64 *val) - DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, - debug_shrink_set, "%llu\n"); - -+static int ion_assign_heap_id(struct ion_heap *heap, struct ion_device *dev) -+{ -+ int id_bit; -+ int start_bit, end_bit; -+ -+ switch (heap->type) { -+ case ION_HEAP_TYPE_SYSTEM: -+ id_bit = ffs(ION_HEAP_SYSTEM); -+ break; -+ case ION_HEAP_TYPE_SYSTEM_CONTIG: -+ id_bit = ffs(ION_HEAP_SYSTEM_CONTIG); -+ break; -+ case ION_HEAP_TYPE_CHUNK: -+ id_bit = ffs(ION_HEAP_CHUNK); -+ break; -+ case ION_HEAP_TYPE_CARVEOUT: -+ id_bit = 0; -+ start_bit = ffs(ION_HEAP_CARVEOUT_START); -+ end_bit = ffs(ION_HEAP_CARVEOUT_END); -+ break; -+ case ION_HEAP_TYPE_DMA: -+ id_bit = 0; -+ start_bit = ffs(ION_HEAP_DMA_START); -+ end_bit = ffs(ION_HEAP_DMA_END); -+ break; -+ case ION_HEAP_TYPE_CUSTOM ... ION_HEAP_TYPE_MAX: -+ id_bit = 0; -+ start_bit = ffs(ION_HEAP_CUSTOM_START); -+ end_bit = ffs(ION_HEAP_CUSTOM_END); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* For carveout, dma & custom heaps, we first let the heaps choose their -+ * own IDs. This allows the old behaviour of knowing the heap ids -+ * of these type of heaps in advance in user space. If a heap with -+ * that ID already exists, it is an error. -+ * -+ * If the heap hasn't picked an id by itself, then we assign it -+ * one. -+ */ -+ if (!id_bit) { -+ if (heap->id) { -+ id_bit = ffs(heap->id); -+ if (id_bit < start_bit || id_bit > end_bit) -+ return -EINVAL; -+ } else { -+ id_bit = find_next_zero_bit(dev->heap_ids, end_bit + 1, -+ start_bit); -+ if (id_bit > end_bit) -+ return -ENOSPC; -+ } -+ } -+ -+ if (test_and_set_bit(id_bit - 1, dev->heap_ids)) -+ return -EEXIST; -+ heap->id = id_bit; -+ dev->heap_cnt++; -+ -+ return 0; -+} -+ - int __ion_device_add_heap(struct ion_heap *heap, struct module *owner) - { - struct ion_device *dev = internal_dev; -@@ -283,7 +346,14 @@ int __ion_device_add_heap(struct ion_heap *heap, struct module *owner) - - heap->debugfs_dir = heap_root; - down_write(&dev->lock); -- heap->id = heap_id++; -+ ret = ion_assign_heap_id(heap, dev); -+ if (ret) { -+ pr_err("%s: Failed to assign heap id for heap type %x\n", -+ __func__, heap->type); -+ up_write(&dev->lock); -+ goto out_debugfs_cleanup; -+ } -+ - /* - * use negative heap->id to reverse the priority -- when traversing - * the list later attempt higher id numbers first -@@ -291,11 +361,12 @@ int __ion_device_add_heap(struct ion_heap *heap, struct module *owner) - plist_node_init(&heap->node, -heap->id); - plist_add(&heap->node, &dev->heaps); - -- dev->heap_cnt++; - up_write(&dev->lock); - - return 0; - -+out_debugfs_cleanup: -+ debugfs_remove_recursive(heap->debugfs_dir); - out_heap_cleanup: - ion_heap_cleanup(heap); - out: -@@ -321,6 +392,8 @@ void ion_device_remove_heap(struct ion_heap *heap) - __func__, heap->name); - } - debugfs_remove_recursive(heap->debugfs_dir); -+ clear_bit(heap->id - 1, dev->heap_ids); -+ dev->heap_cnt--; - up_write(&dev->lock); - } - EXPORT_SYMBOL(ion_device_remove_heap); -diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h -index 5cc09fbfbefe..2f5376e131c3 100644 ---- a/drivers/staging/android/ion/ion_private.h -+++ b/drivers/staging/android/ion/ion_private.h -@@ -23,13 +23,16 @@ - * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers -- * @lock: rwsem protecting the tree of heaps and clients -+ * @lock: rwsem protecting the tree of heaps, heap_bitmap and -+ * clients -+ * @heap_ids: bitmap of register heap ids - */ - struct ion_device { - struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; - struct rw_semaphore lock; -+ DECLARE_BITMAP(heap_ids, ION_NUM_MAX_HEAPS); - struct plist_head heaps; - struct dentry *debug_root; - int heap_cnt; diff --git a/patches/ANDROID-staging-ion-export-ion_free-for-ion_heaps.patch b/patches/ANDROID-staging-ion-export-ion_free-for-ion_heaps.patch deleted file mode 100644 index 4ede4c8a29d176777361f5a2c5d7b4eca5b50358..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-export-ion_free-for-ion_heaps.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Tue, 10 Sep 2019 05:13:51 -0700 -Subject: ANDROID: staging: ion: export ion_free() for ion_heaps. - -ion_free() is a generic function needed to release -an ion buffer back to the heap. So, export it for the -heap module. - -Bug: 140294230 -Test: ion-unit-tests - -Change-Id: Iaa467ab3df18fa219412dd9f5913cd022a93455d -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion.c | 1 + - include/linux/ion.h | 12 ++++++++++++ - 2 files changed, 13 insertions(+) - -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index aaa02c671a91..2c915579f60b 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -41,6 +41,7 @@ int ion_free(struct ion_buffer *buffer) - { - return ion_buffer_destroy(internal_dev, buffer); - } -+EXPORT_SYMBOL_GPL(ion_free); - - static int ion_alloc_fd(size_t len, unsigned int heap_id_mask, - unsigned int flags) -diff --git a/include/linux/ion.h b/include/linux/ion.h -index 87aa2bcec7d3..88622fb8f9ea 100644 ---- a/include/linux/ion.h -+++ b/include/linux/ion.h -@@ -293,6 +293,13 @@ int ion_buffer_zero(struct ion_buffer *buffer); - struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - unsigned int flags); - -+/** -+ * ion_free - Releases the ion buffer. -+ * -+ * @buffer: ion buffer to be released -+ */ -+int ion_free(struct ion_buffer *buffer); -+ - #else - - static inline int __ion_device_add_heap(struct ion_heap *heap, -@@ -357,5 +364,10 @@ static inline struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - return ERR_PTR(-ENOMEM); - } - -+static inline int ion_free(struct ion_buffer *buffer) -+{ -+ return 0; -+} -+ - #endif /* CONFIG_ION */ - #endif /* _ION_KERNEL_H */ diff --git a/patches/ANDROID-staging-ion-fix-off-by-1-error-in-heap-search.patch b/patches/ANDROID-staging-ion-fix-off-by-1-error-in-heap-search.patch deleted file mode 100644 index cb66ae6b316804a8f37c72b5bcbf800726677eba..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-fix-off-by-1-error-in-heap-search.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Mon, 9 Sep 2019 08:21:20 -0700 -Subject: ANDROID: staging: ion: fix off-by-1 error in heap search - -ion allocation was wrong because of an off-by-1 error -in heap search for buffer allocation. Fix it. - -Bug: 140507100 -Test: ion-unit-tests - -Change-Id: I6ac5b0ddc6b31b5409645f62a96781d464b7bdf3 -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index c8ed051715bc..aaa02c671a91 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -279,7 +279,7 @@ static int ion_assign_heap_id(struct ion_heap *heap, struct ion_device *dev) - - if (test_and_set_bit(id_bit - 1, dev->heap_ids)) - return -EEXIST; -- heap->id = id_bit; -+ heap->id = id_bit - 1; - dev->heap_cnt++; - - return 0; -@@ -392,7 +392,7 @@ void ion_device_remove_heap(struct ion_heap *heap) - __func__, heap->name); - } - debugfs_remove_recursive(heap->debugfs_dir); -- clear_bit(heap->id - 1, dev->heap_ids); -+ clear_bit(heap->id, dev->heap_ids); - dev->heap_cnt--; - up_write(&dev->lock); - } diff --git a/patches/ANDROID-staging-ion-fix-sparse-warning-in-ion-system-heap.patch b/patches/ANDROID-staging-ion-fix-sparse-warning-in-ion-system-heap.patch deleted file mode 100644 index 6cfa27b7a9263f2562d64e08acc0be7bad53ed30..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-fix-sparse-warning-in-ion-system-heap.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Wed, 9 Oct 2019 21:38:04 -0700 -Subject: ANDROID: staging: ion: fix sparse warning in ion system heap - -drivers/staging/android/ion/heaps/ion_system_heap.c:250:24: sparse: sparse: -symbol 'system_heap' was not declared. Should it be static? - -Fixes: 142434553 -Test: Build and boot cuttlefish - -Change-Id: I6e1eb9365ca12c2d081533ed2db9881086531ec7 -Reported-by: kbuild test robot -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/heaps/ion_system_heap.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/staging/android/ion/heaps/ion_system_heap.c b/drivers/staging/android/ion/heaps/ion_system_heap.c -index 792cd130e493..054324784ab9 100644 ---- a/drivers/staging/android/ion/heaps/ion_system_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_heap.c -@@ -244,7 +244,7 @@ static struct ion_heap_ops system_heap_ops = { - .shrink = ion_system_heap_shrink, - }; - --struct ion_system_heap system_heap = { -+static struct ion_system_heap system_heap = { - .heap = { - .ops = &system_heap_ops, - .type = ION_HEAP_TYPE_SYSTEM, diff --git a/patches/ANDROID-staging-ion-make-cma-heap-a-module.patch b/patches/ANDROID-staging-ion-make-cma-heap-a-module.patch deleted file mode 100644 index 0ad88c8f4eebbef6ccf770928bd87dc36fc44de4..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-make-cma-heap-a-module.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Fri, 13 Sep 2019 14:52:14 -0700 -Subject: ANDROID: staging: ion: make cma heap a module - -Add all cma areas that we can find as cma heaps. - -Bug: 133508579 -Test: build and insmod ion_cma_heap - -Change-Id: I3cf1884c8d8914ae31d55e2f2770104347844036 -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/heaps/Kconfig | 2 +- - .../staging/android/ion/heaps/ion_cma_heap.c | 56 ++++++++++++------- - 2 files changed, 36 insertions(+), 22 deletions(-) - -diff --git a/drivers/staging/android/ion/heaps/Kconfig b/drivers/staging/android/ion/heaps/Kconfig -index af6fce69e61a..617d6e7ea583 100644 ---- a/drivers/staging/android/ion/heaps/Kconfig -+++ b/drivers/staging/android/ion/heaps/Kconfig -@@ -15,7 +15,7 @@ config ION_SYSTEM_CONTIG_HEAP - contiguous. If in doubt, say Y. - - config ION_CMA_HEAP -- bool "Ion CMA heap support" -+ tristate "Ion CMA heap support" - depends on ION && DMA_CMA - help - Choose this option to enable CMA heaps with Ion. This heap is backed -diff --git a/drivers/staging/android/ion/heaps/ion_cma_heap.c b/drivers/staging/android/ion/heaps/ion_cma_heap.c -index 236b6c576cdb..9584972b5005 100644 ---- a/drivers/staging/android/ion/heaps/ion_cma_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_cma_heap.c -@@ -18,7 +18,7 @@ - struct ion_cma_heap { - struct ion_heap heap; - struct cma *cma; --}; -+} cma_heaps[MAX_CMA_AREAS]; - - #define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap) - -@@ -97,38 +97,52 @@ static struct ion_heap_ops ion_cma_ops = { - .free = ion_cma_free, - }; - --static struct ion_heap *__ion_cma_heap_create(struct cma *cma) -+static int __ion_add_cma_heap(struct cma *cma, void *data) - { -+ int *cma_nr = data; - struct ion_cma_heap *cma_heap; -+ int ret; - -- cma_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL); -- -- if (!cma_heap) -- return ERR_PTR(-ENOMEM); -+ if (*cma_nr >= MAX_CMA_AREAS) -+ return -EINVAL; - -+ cma_heap = &cma_heaps[*cma_nr]; - cma_heap->heap.ops = &ion_cma_ops; -- cma_heap->cma = cma; - cma_heap->heap.type = ION_HEAP_TYPE_DMA; -- return &cma_heap->heap; -+ cma_heap->heap.name = cma_get_name(cma); -+ -+ ret = ion_device_add_heap(&cma_heap->heap); -+ if (ret) -+ goto out; -+ -+ cma_heap->cma = cma; -+ *cma_nr += 1; -+out: -+ return 0; - } - --static int __ion_add_cma_heaps(struct cma *cma, void *data) -+static int __init ion_cma_heap_init(void) - { -- struct ion_heap *heap; -- -- heap = __ion_cma_heap_create(cma); -- if (IS_ERR(heap)) -- return PTR_ERR(heap); -+ int ret; -+ int nr = 0; - -- heap->name = cma_get_name(cma); -+ ret = cma_for_each_area(__ion_add_cma_heap, &nr); -+ if (ret) { -+ for (nr = 0; nr < MAX_CMA_AREAS && cma_heaps[nr].cma; nr++) -+ ion_device_remove_heap(&cma_heaps[nr].heap); -+ } - -- ion_device_add_heap(heap); -- return 0; -+ return ret; - } - --static int ion_add_cma_heaps(void) -+static void __exit ion_cma_heap_exit(void) - { -- cma_for_each_area(__ion_add_cma_heaps, NULL); -- return 0; -+ int nr; -+ -+ for (nr = 0; nr < MAX_CMA_AREAS && cma_heaps[nr].cma; nr++) -+ ion_device_remove_heap(&cma_heaps[nr].heap); - } --device_initcall(ion_add_cma_heaps); -+ -+module_init(ion_cma_heap_init); -+module_exit(ion_cma_heap_exit); -+MODULE_LICENSE("GPL v2"); diff --git a/patches/ANDROID-staging-ion-make-system-and-contig-heaps-modular.patch b/patches/ANDROID-staging-ion-make-system-and-contig-heaps-modular.patch deleted file mode 100644 index 833b0c6ea2c17496e79d8d0759a9f06b09fda54d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-make-system-and-contig-heaps-modular.patch +++ /dev/null @@ -1,512 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Mon, 12 Aug 2019 17:23:25 -0700 -Subject: ANDROID: staging: ion: make system and contig heaps modular - -Add symmetric heap add/remove APIs and export symbols from -ion core that are needed to make both heaps modular. - -Bug: 133508579 -Test: ion-unit-test, rmmod, modprobe - -Change-Id: Ic5f40936531936c9bfab48ea147108c019d28e2c -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/heaps/Kconfig | 4 +- - drivers/staging/android/ion/heaps/Makefile | 4 +- - .../ion/heaps/ion_system_contig_heap.c | 36 ++++------ - .../android/ion/heaps/ion_system_heap.c | 67 +++++++++---------- - drivers/staging/android/ion/ion.c | 54 ++++++++++++--- - drivers/staging/android/ion/ion_buffer.c | 13 ++++ - drivers/staging/android/ion/ion_heap.c | 39 ++++++++++- - drivers/staging/android/ion/ion_private.h | 3 + - include/linux/ion.h | 24 ++++++- - 9 files changed, 169 insertions(+), 75 deletions(-) - -diff --git a/drivers/staging/android/ion/heaps/Kconfig b/drivers/staging/android/ion/heaps/Kconfig -index f1c7a6b79c01..af6fce69e61a 100644 ---- a/drivers/staging/android/ion/heaps/Kconfig -+++ b/drivers/staging/android/ion/heaps/Kconfig -@@ -1,13 +1,13 @@ - # SPDX-License-Identifier: GPL-2.0 - config ION_SYSTEM_HEAP -- bool "Ion system heap" -+ tristate "Ion system heap" - depends on ION - help - Choose this option to enable the Ion system heap. The system heap - is backed by pages from the buddy allocator. If in doubt, say Y. - - config ION_SYSTEM_CONTIG_HEAP -- bool "Ion system contig heap" -+ tristate "Ion system contig heap" - depends on ION - help - Choose this option to enable Ion system contig heap. The system contig heap -diff --git a/drivers/staging/android/ion/heaps/Makefile b/drivers/staging/android/ion/heaps/Makefile -index e2ee931100d0..449879035877 100644 ---- a/drivers/staging/android/ion/heaps/Makefile -+++ b/drivers/staging/android/ion/heaps/Makefile -@@ -1,4 +1,6 @@ - # SPDX-License-Identifier: GPL-2.0 --obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o -+obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_sys_heap.o -+ion_sys_heap-y := ion_system_heap.o ion_page_pool.o -+ - obj-$(CONFIG_ION_SYSTEM_CONTIG_HEAP) += ion_system_contig_heap.o - obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -diff --git a/drivers/staging/android/ion/heaps/ion_system_contig_heap.c b/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -index 3a07ef931c2e..9cb18e38dc96 100644 ---- a/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -81,31 +82,22 @@ static struct ion_heap_ops kmalloc_ops = { - .map_user = ion_heap_map_user, - }; - --static struct ion_heap *__ion_system_contig_heap_create(void) --{ -- struct ion_heap *heap; -- -- heap = kzalloc(sizeof(*heap), GFP_KERNEL); -- if (!heap) -- return ERR_PTR(-ENOMEM); -- heap->ops = &kmalloc_ops; -- heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; -- heap->name = "ion_system_contig_heap"; -+static struct ion_heap contig_heap = { -+ .ops = &kmalloc_ops, -+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG, -+ .name = "ion_system_contig_heap", -+}; - -- return heap; -+static int __init ion_system_contig_heap_init(void) -+{ -+ return ion_device_add_heap(&contig_heap); - } - --static int ion_system_contig_heap_create(void) -+static void __exit ion_system_contig_heap_exit(void) - { -- struct ion_heap *heap; -- -- heap = __ion_system_contig_heap_create(); -- if (IS_ERR(heap)) -- return PTR_ERR(heap); -- -- ion_device_add_heap(heap); -- -- return 0; -+ ion_device_remove_heap(&contig_heap); - } --device_initcall(ion_system_contig_heap_create); - -+module_init(ion_system_contig_heap_init); -+module_exit(ion_system_contig_heap_exit); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/staging/android/ion/heaps/ion_system_heap.c b/drivers/staging/android/ion/heaps/ion_system_heap.c -index 25ea31757578..3aed952c219d 100644 ---- a/drivers/staging/android/ion/heaps/ion_system_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_heap.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -204,15 +205,6 @@ static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, - return nr_total; - } - --static struct ion_heap_ops system_heap_ops = { -- .allocate = ion_system_heap_allocate, -- .free = ion_system_heap_free, -- .map_kernel = ion_heap_map_kernel, -- .unmap_kernel = ion_heap_unmap_kernel, -- .map_user = ion_heap_map_user, -- .shrink = ion_system_heap_shrink, --}; -- - static void ion_system_heap_destroy_pools(struct ion_page_pool **pools) - { - int i; -@@ -246,38 +238,39 @@ static int ion_system_heap_create_pools(struct ion_page_pool **pools) - return -ENOMEM; - } - --static struct ion_heap *__ion_system_heap_create(void) --{ -- struct ion_system_heap *heap; -- -- heap = kzalloc(sizeof(*heap), GFP_KERNEL); -- if (!heap) -- return ERR_PTR(-ENOMEM); -- heap->heap.ops = &system_heap_ops; -- heap->heap.type = ION_HEAP_TYPE_SYSTEM; -- heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; -+static struct ion_heap_ops system_heap_ops = { -+ .allocate = ion_system_heap_allocate, -+ .free = ion_system_heap_free, -+ .map_kernel = ion_heap_map_kernel, -+ .unmap_kernel = ion_heap_unmap_kernel, -+ .map_user = ion_heap_map_user, -+ .shrink = ion_system_heap_shrink, -+}; - -- if (ion_system_heap_create_pools(heap->pools)) -- goto free_heap; -+struct ion_system_heap system_heap = { -+ .heap = { -+ .ops = &system_heap_ops, -+ .type = ION_HEAP_TYPE_SYSTEM, -+ .flags = ION_HEAP_FLAG_DEFER_FREE, -+ .name = "ion_system_heap", -+ } -+}; - -- return &heap->heap; -+static int __init ion_system_heap_init(void) -+{ -+ int ret = ion_system_heap_create_pools(system_heap.pools); -+ if (ret) -+ return ret; - --free_heap: -- kfree(heap); -- return ERR_PTR(-ENOMEM); -+ return ion_device_add_heap(&system_heap.heap); - } - --static int ion_system_heap_create(void) -+static void __exit ion_system_heap_exit(void) - { -- struct ion_heap *heap; -- -- heap = __ion_system_heap_create(); -- if (IS_ERR(heap)) -- return PTR_ERR(heap); -- heap->name = "ion_system_heap"; -- -- ion_device_add_heap(heap); -- -- return 0; -+ ion_device_remove_heap(&system_heap.heap); -+ ion_system_heap_destroy_pools(system_heap.pools); - } --device_initcall(ion_system_heap_create); -+ -+module_init(ion_system_heap_init); -+module_exit(ion_system_heap_exit); -+MODULE_LICENSE("GPL v2"); -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index b862bdfeca89..548d65dbd3ac 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -222,28 +222,36 @@ static int debug_shrink_get(void *data, u64 *val) - DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, - debug_shrink_set, "%llu\n"); - --void ion_device_add_heap(struct ion_heap *heap) -+int __ion_device_add_heap(struct ion_heap *heap, struct module *owner) - { - struct ion_device *dev = internal_dev; - int ret; - struct dentry *heap_root; - char debug_name[64]; - -- if (!heap->ops->allocate || !heap->ops->free) -- pr_err("%s: can not add heap with invalid ops struct.\n", -- __func__); -+ if (!heap || !heap->ops || !heap->ops->allocate || !heap->ops->free) { -+ pr_err("%s: invalid heap or heap_ops\n", __func__); -+ ret = -EINVAL; -+ goto out; -+ } - -+ heap->owner = owner; - spin_lock_init(&heap->free_lock); - spin_lock_init(&heap->stat_lock); - heap->free_list_size = 0; - -- if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) -- ion_heap_init_deferred_free(heap); -+ if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) { -+ ret = ion_heap_init_deferred_free(heap); -+ if (ret) -+ goto out_heap_cleanup; -+ } - - if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink) { - ret = ion_heap_init_shrinker(heap); -- if (ret) -+ if (ret) { - pr_err("%s: Failed to register shrinker\n", __func__); -+ goto out_heap_cleanup; -+ } - } - - heap->num_of_buffers = 0; -@@ -273,6 +281,7 @@ void ion_device_add_heap(struct ion_heap *heap) - &debug_shrink_fops); - } - -+ heap->debugfs_dir = heap_root; - down_write(&dev->lock); - heap->id = heap_id++; - /* -@@ -284,8 +293,37 @@ void ion_device_add_heap(struct ion_heap *heap) - - dev->heap_cnt++; - up_write(&dev->lock); -+ -+ return 0; -+ -+out_heap_cleanup: -+ ion_heap_cleanup(heap); -+out: -+ return ret; -+} -+EXPORT_SYMBOL_GPL(__ion_device_add_heap); -+ -+void ion_device_remove_heap(struct ion_heap *heap) -+{ -+ struct ion_device *dev = internal_dev; -+ -+ if (!heap) { -+ pr_err("%s: Invalid argument\n", __func__); -+ return; -+ } -+ -+ // take semaphore and remove the heap from dev->heap list -+ down_write(&dev->lock); -+ /* So no new allocations can happen from this heap */ -+ plist_del(&heap->node, &dev->heaps); -+ if (ion_heap_cleanup(heap) != 0) { -+ pr_warn("%s: failed to cleanup heap (%s)\n", -+ __func__, heap->name); -+ } -+ debugfs_remove_recursive(heap->debugfs_dir); -+ up_write(&dev->lock); - } --EXPORT_SYMBOL(ion_device_add_heap); -+EXPORT_SYMBOL(ion_device_remove_heap); - - static int ion_device_create(void) - { -diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c -index adce2d489f56..879b3ddb08c0 100644 ---- a/drivers/staging/android/ion/ion_buffer.c -+++ b/drivers/staging/android/ion/ion_buffer.c -@@ -6,6 +6,7 @@ - */ - - #include -+#include - #include - - #include "ion_private.h" -@@ -76,6 +77,14 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, - heap->num_of_alloc_bytes += len; - if (heap->num_of_alloc_bytes > heap->alloc_bytes_wm) - heap->alloc_bytes_wm = heap->num_of_alloc_bytes; -+ if (heap->num_of_buffers == 1) { -+ /* This module reference lasts as long as at least one -+ * buffer is allocated from the heap. We are protected -+ * against ion_device_remove_heap() with dev->lock, so we can -+ * safely assume the module reference is going to* succeed. -+ */ -+ __module_get(heap->owner); -+ } - spin_unlock(&heap->stat_lock); - - INIT_LIST_HEAD(&buffer->attachments); -@@ -184,6 +193,7 @@ int ion_buffer_zero(struct ion_buffer *buffer) - - return ion_sglist_zero(table->sgl, table->nents, pgprot); - } -+EXPORT_SYMBOL_GPL(ion_buffer_zero); - - void ion_buffer_release(struct ion_buffer *buffer) - { -@@ -196,7 +206,10 @@ void ion_buffer_release(struct ion_buffer *buffer) - spin_lock(&buffer->heap->stat_lock); - buffer->heap->num_of_buffers--; - buffer->heap->num_of_alloc_bytes -= buffer->size; -+ if (buffer->heap->num_of_buffers == 0) -+ module_put(buffer->heap->owner); - spin_unlock(&buffer->heap->stat_lock); -+ /* drop reference to the heap module */ - - kfree(buffer); - } -diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c -index 755548a4382d..e102f6a2ecf6 100644 ---- a/drivers/staging/android/ion/ion_heap.c -+++ b/drivers/staging/android/ion/ion_heap.c -@@ -101,12 +101,15 @@ static int ion_heap_deferred_free(void *data) - struct ion_buffer *buffer; - - wait_event_freezable(heap->waitqueue, -- ion_heap_freelist_size(heap) > 0); -+ (ion_heap_freelist_size(heap) > 0 || -+ kthread_should_stop())); - - spin_lock(&heap->free_lock); - if (list_empty(&heap->free_list)) { - spin_unlock(&heap->free_lock); -- continue; -+ if (!kthread_should_stop()) -+ continue; -+ break; - } - buffer = list_first_entry(&heap->free_list, struct ion_buffer, - list); -@@ -156,12 +159,14 @@ void *ion_heap_map_kernel(struct ion_heap *heap, - - return vaddr; - } -+EXPORT_SYMBOL_GPL(ion_heap_map_kernel); - - void ion_heap_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) - { - vunmap(buffer->vaddr); - } -+EXPORT_SYMBOL_GPL(ion_heap_unmap_kernel); - - int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma) -@@ -198,6 +203,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - - return 0; - } -+EXPORT_SYMBOL_GPL(ion_heap_map_user); - - void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer) - { -@@ -256,3 +262,32 @@ int ion_heap_init_shrinker(struct ion_heap *heap) - - return register_shrinker(&heap->shrinker); - } -+ -+int ion_heap_cleanup(struct ion_heap *heap) -+{ -+ int ret; -+ -+ if (heap->flags & ION_HEAP_FLAG_DEFER_FREE && -+ !IS_ERR_OR_NULL(heap->task)) { -+ size_t free_list_size = ion_heap_freelist_size(heap); -+ size_t total_drained = ion_heap_freelist_drain(heap, 0); -+ -+ if (total_drained != free_list_size) { -+ pr_err("%s: %s heap drained %zu bytes, requested %zu\n", -+ __func__, heap->name, free_list_size, -+ total_drained); -+ return -EBUSY; -+ } -+ ret = kthread_stop(heap->task); -+ if (ret < 0) { -+ pr_err("%s: failed to stop heap free thread\n", -+ __func__); -+ return ret; -+ } -+ } -+ -+ if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink) -+ unregister_shrinker(&heap->shrinker); -+ -+ return 0; -+} -diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h -index ed7ed39d0df1..5cc09fbfbefe 100644 ---- a/drivers/staging/android/ion/ion_private.h -+++ b/drivers/staging/android/ion/ion_private.h -@@ -51,4 +51,7 @@ extern struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, - unsigned int flags); - extern int ion_free(struct ion_buffer *buffer); - -+/* ion heap helpers */ -+extern int ion_heap_cleanup(struct ion_heap *heap); -+ - #endif /* _ION_PRIVATE_H */ -diff --git a/include/linux/ion.h b/include/linux/ion.h -index 775e948a362c..fe0d2cb1ef25 100644 ---- a/include/linux/ion.h -+++ b/include/linux/ion.h -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -105,6 +106,7 @@ struct ion_heap_ops { - * allocating. These are specified by platform data and - * MUST be unique - * @name: used for debugging -+ * @owner: kernel module that implements this heap - * @shrinker: a shrinker for the heap - * @free_list: free list head if deferred free is used - * @free_list_size size of the deferred free list in bytes -@@ -127,6 +129,7 @@ struct ion_heap { - unsigned long flags; - unsigned int id; - const char *name; -+ struct module *owner; - - /* deferred free support */ - struct shrinker shrinker; -@@ -143,16 +146,30 @@ struct ion_heap { - - /* protect heap statistics */ - spinlock_t stat_lock; -+ -+ /* heap's debugfs root */ -+ struct dentry *debugfs_dir; - }; - -+#define ion_device_add_heap(heap) __ion_device_add_heap(heap, THIS_MODULE) -+ - #ifdef CONFIG_ION - - /** -- * ion_device_add_heap - adds a heap to the ion device -+ * __ion_device_add_heap - adds a heap to the ion device - * - * @heap: the heap to add -+ * -+ * Returns 0 on success, negative error otherwise. -+ */ -+int __ion_device_add_heap(struct ion_heap *heap, struct module *owner); -+ -+/** -+ * ion_device_remove_heap - removes a heap from ion device -+ * -+ * @heap: pointer to the heap to be removed - */ --void ion_device_add_heap(struct ion_heap *heap); -+void ion_device_remove_heap(struct ion_heap *heap); - - /** - * ion_heap_init_shrinker -@@ -283,7 +300,8 @@ struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - - #else - --static inline int ion_device_add_heap(struct ion_heap *heap) -+static inline int __ion_device_add_heap(struct ion_heap *heap, -+ struct module *owner) - { - return -ENODEV; - } diff --git a/patches/ANDROID-staging-ion-move-uapi-ion.h-to-uapi-linux-ion.h.patch b/patches/ANDROID-staging-ion-move-uapi-ion.h-to-uapi-linux-ion.h.patch deleted file mode 100644 index f998db8740685e8de1ea751389812f95caab3e6a..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-move-uapi-ion.h-to-uapi-linux-ion.h.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Mon, 26 Aug 2019 12:39:52 -0700 -Subject: ANDROID: staging: ion: move uapi/ion.h to uapi/linux/ion.h - -Bug: 133508579 -Test: builds - -Change-Id: I599a78e1acd2eed909f40e5a5b6a62813610990c -Signed-off-by: Sandeep Patil ---- - include/linux/ion.h | 2 +- - include/uapi/{ => linux}/ion.h | 0 - 2 files changed, 1 insertion(+), 1 deletion(-) - rename include/uapi/{ => linux}/ion.h (100%) - -diff --git a/include/linux/ion.h b/include/linux/ion.h -index fe0d2cb1ef25..5d68674b015a 100644 ---- a/include/linux/ion.h -+++ b/include/linux/ion.h -@@ -18,7 +18,7 @@ - #include - #include - #include --#include -+#include - - /** - * struct ion_buffer - metadata for a particular buffer -diff --git a/include/uapi/ion.h b/include/uapi/linux/ion.h -similarity index 100% -rename from include/uapi/ion.h -rename to include/uapi/linux/ion.h diff --git a/patches/ANDROID-staging-ion-refactor-ion-s-buffer-manipulators-into-a-separate-file.patch b/patches/ANDROID-staging-ion-refactor-ion-s-buffer-manipulators-into-a-separate-file.patch deleted file mode 100644 index 3a7c17e3a2ec2102663dd8824b2041e620d555f2..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-refactor-ion-s-buffer-manipulators-into-a-separate-file.patch +++ /dev/null @@ -1,552 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Wed, 7 Aug 2019 12:12:47 -0700 -Subject: ANDROID: staging: ion: refactor ion's buffer manipulators into a - separate file. - -This patch is preparatory work for making ion heaps modular. The patch -itself doesn't make any significant changes except for re-organizing the -buffer manipulator functions in a single file. This will be helpful -later when we specifically export some of these functions to be used by -a heap module. - -Bug: 133508579 -Test: ion-unit-tests - -Change-Id: I7438bd529a3e9c7a90910979e26bd754a8292e9a -Co-developed-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/Makefile | 2 +- - drivers/staging/android/ion/ion.c | 143 +--------------- - drivers/staging/android/ion/ion.h | 15 -- - drivers/staging/android/ion/ion_buffer.c | 198 ++++++++++++++++++++++ - drivers/staging/android/ion/ion_heap.c | 6 +- - drivers/staging/android/ion/ion_private.h | 47 +++++ - 6 files changed, 254 insertions(+), 157 deletions(-) - create mode 100644 drivers/staging/android/ion/ion_buffer.c - create mode 100644 drivers/staging/android/ion/ion_private.h - -diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile -index 5f4487b1a224..da386dbf3ffd 100644 ---- a/drivers/staging/android/ion/Makefile -+++ b/drivers/staging/android/ion/Makefile -@@ -1,4 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0 --obj-$(CONFIG_ION) += ion.o ion_heap.o -+obj-$(CONFIG_ION) += ion.o ion_buffer.o ion_heap.o - obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o - obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index 2e5c6ae2f3fc..19d3e82b2f5b 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -26,119 +26,11 @@ - #include - #include - --#include "ion.h" -+#include "ion_private.h" - - static struct ion_device *internal_dev; - static int heap_id; - --/* this function should only be called while dev->lock is held */ --static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, -- struct ion_device *dev, -- unsigned long len, -- unsigned long flags) --{ -- struct ion_buffer *buffer; -- int ret; -- -- buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); -- if (!buffer) -- return ERR_PTR(-ENOMEM); -- -- buffer->heap = heap; -- buffer->flags = flags; -- buffer->dev = dev; -- buffer->size = len; -- -- ret = heap->ops->allocate(heap, buffer, len, flags); -- -- if (ret) { -- if (!(heap->flags & ION_HEAP_FLAG_DEFER_FREE)) -- goto err2; -- -- ion_heap_freelist_drain(heap, 0); -- ret = heap->ops->allocate(heap, buffer, len, flags); -- if (ret) -- goto err2; -- } -- -- if (!buffer->sg_table) { -- WARN_ONCE(1, "This heap needs to set the sgtable"); -- ret = -EINVAL; -- goto err1; -- } -- -- spin_lock(&heap->stat_lock); -- heap->num_of_buffers++; -- heap->num_of_alloc_bytes += len; -- if (heap->num_of_alloc_bytes > heap->alloc_bytes_wm) -- heap->alloc_bytes_wm = heap->num_of_alloc_bytes; -- spin_unlock(&heap->stat_lock); -- -- INIT_LIST_HEAD(&buffer->attachments); -- mutex_init(&buffer->lock); -- return buffer; -- --err1: -- heap->ops->free(buffer); --err2: -- kfree(buffer); -- return ERR_PTR(ret); --} -- --void ion_buffer_destroy(struct ion_buffer *buffer) --{ -- if (buffer->kmap_cnt > 0) { -- pr_warn_once("%s: buffer still mapped in the kernel\n", -- __func__); -- buffer->heap->ops->unmap_kernel(buffer->heap, buffer); -- } -- buffer->heap->ops->free(buffer); -- spin_lock(&buffer->heap->stat_lock); -- buffer->heap->num_of_buffers--; -- buffer->heap->num_of_alloc_bytes -= buffer->size; -- spin_unlock(&buffer->heap->stat_lock); -- -- kfree(buffer); --} -- --static void _ion_buffer_destroy(struct ion_buffer *buffer) --{ -- struct ion_heap *heap = buffer->heap; -- -- if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) -- ion_heap_freelist_add(heap, buffer); -- else -- ion_buffer_destroy(buffer); --} -- --static void *ion_buffer_kmap_get(struct ion_buffer *buffer) --{ -- void *vaddr; -- -- if (buffer->kmap_cnt) { -- buffer->kmap_cnt++; -- return buffer->vaddr; -- } -- vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); -- if (WARN_ONCE(!vaddr, -- "heap->ops->map_kernel should return ERR_PTR on error")) -- return ERR_PTR(-EINVAL); -- if (IS_ERR(vaddr)) -- return vaddr; -- buffer->vaddr = vaddr; -- buffer->kmap_cnt++; -- return vaddr; --} -- --static void ion_buffer_kmap_put(struct ion_buffer *buffer) --{ -- buffer->kmap_cnt--; -- if (!buffer->kmap_cnt) { -- buffer->heap->ops->unmap_kernel(buffer->heap, buffer); -- buffer->vaddr = NULL; -- } --} -- - static struct sg_table *dup_sg_table(struct sg_table *table) - { - struct sg_table *new_table; -@@ -273,7 +165,7 @@ static void ion_dma_buf_release(struct dma_buf *dmabuf) - { - struct ion_buffer *buffer = dmabuf->priv; - -- _ion_buffer_destroy(buffer); -+ ion_buffer_destroy(internal_dev, buffer); - } - - static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) -@@ -358,39 +250,14 @@ static const struct dma_buf_ops dma_buf_ops = { - static struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask, - unsigned int flags) - { -- struct ion_device *dev = internal_dev; -- struct ion_buffer *buffer = NULL; -- struct ion_heap *heap; -+ struct ion_buffer *buffer; - DEFINE_DMA_BUF_EXPORT_INFO(exp_info); - struct dma_buf *dmabuf; - - pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, - len, heap_id_mask, flags); -- /* -- * traverse the list of heaps available in this system in priority -- * order. If the heap type is supported by the client, and matches the -- * request of the caller allocate from it. Repeat until allocate has -- * succeeded or all heaps have been tried -- */ -- len = PAGE_ALIGN(len); -- -- if (!len) -- return ERR_PTR(-EINVAL); -- -- down_read(&dev->lock); -- plist_for_each_entry(heap, &dev->heaps, node) { -- /* if the caller didn't specify this heap id */ -- if (!((1 << heap->id) & heap_id_mask)) -- continue; -- buffer = ion_buffer_create(heap, dev, len, flags); -- if (!IS_ERR(buffer)) -- break; -- } -- up_read(&dev->lock); -- -- if (!buffer) -- return ERR_PTR(-ENODEV); - -+ buffer = ion_buffer_alloc(internal_dev, len, heap_id_mask, flags); - if (IS_ERR(buffer)) - return ERR_CAST(buffer); - -@@ -401,7 +268,7 @@ static struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask, - - dmabuf = dma_buf_export(&exp_info); - if (IS_ERR(dmabuf)) -- _ion_buffer_destroy(buffer); -+ ion_buffer_destroy(internal_dev, buffer); - - return dmabuf; - } -diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h -index 6f9f7c365f38..d2d18f03ac77 100644 ---- a/drivers/staging/android/ion/ion.h -+++ b/drivers/staging/android/ion/ion.h -@@ -17,7 +17,6 @@ - #include - #include - #include --#include - - #include "../uapi/ion.h" - -@@ -39,7 +38,6 @@ - */ - struct ion_buffer { - struct list_head list; -- struct ion_device *dev; - struct ion_heap *heap; - unsigned long flags; - unsigned long private_flags; -@@ -54,19 +52,6 @@ struct ion_buffer { - - void ion_buffer_destroy(struct ion_buffer *buffer); - --/** -- * struct ion_device - the metadata of the ion device node -- * @dev: the actual misc device -- * @lock: rwsem protecting the tree of heaps and clients -- */ --struct ion_device { -- struct miscdevice dev; -- struct rw_semaphore lock; -- struct plist_head heaps; -- struct dentry *debug_root; -- int heap_cnt; --}; -- - /** - * struct ion_heap_ops - ops to operate on a given heap - * @allocate: allocate memory -diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c -new file mode 100644 -index 000000000000..8b8dd1e216d4 ---- /dev/null -+++ b/drivers/staging/android/ion/ion_buffer.c -@@ -0,0 +1,198 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * ION Memory Allocator - buffer interface -+ * -+ * Copyright (c) 2019, Google, Inc. -+ */ -+ -+#include -+#include -+ -+#include "ion_private.h" -+ -+/* this function should only be called while dev->lock is held */ -+static void ion_buffer_add(struct ion_device *dev, -+ struct ion_buffer *buffer) -+{ -+ struct rb_node **p = &dev->buffers.rb_node; -+ struct rb_node *parent = NULL; -+ struct ion_buffer *entry; -+ -+ while (*p) { -+ parent = *p; -+ entry = rb_entry(parent, struct ion_buffer, node); -+ -+ if (buffer < entry) { -+ p = &(*p)->rb_left; -+ } else if (buffer > entry) { -+ p = &(*p)->rb_right; -+ } else { -+ pr_err("%s: buffer already found.", __func__); -+ BUG(); -+ } -+ } -+ -+ rb_link_node(&buffer->node, parent, p); -+ rb_insert_color(&buffer->node, &dev->buffers); -+} -+ -+/* this function should only be called while dev->lock is held */ -+static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, -+ struct ion_device *dev, -+ unsigned long len, -+ unsigned long flags) -+{ -+ struct ion_buffer *buffer; -+ int ret; -+ -+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); -+ if (!buffer) -+ return ERR_PTR(-ENOMEM); -+ -+ buffer->heap = heap; -+ buffer->flags = flags; -+ buffer->size = len; -+ -+ ret = heap->ops->allocate(heap, buffer, len, flags); -+ -+ if (ret) { -+ if (!(heap->flags & ION_HEAP_FLAG_DEFER_FREE)) -+ goto err2; -+ -+ ion_heap_freelist_drain(heap, 0); -+ ret = heap->ops->allocate(heap, buffer, len, flags); -+ if (ret) -+ goto err2; -+ } -+ -+ if (!buffer->sg_table) { -+ WARN_ONCE(1, "This heap needs to set the sgtable"); -+ ret = -EINVAL; -+ goto err1; -+ } -+ -+ spin_lock(&heap->stat_lock); -+ heap->num_of_buffers++; -+ heap->num_of_alloc_bytes += len; -+ if (heap->num_of_alloc_bytes > heap->alloc_bytes_wm) -+ heap->alloc_bytes_wm = heap->num_of_alloc_bytes; -+ spin_unlock(&heap->stat_lock); -+ -+ INIT_LIST_HEAD(&buffer->attachments); -+ mutex_init(&buffer->lock); -+ mutex_lock(&dev->buffer_lock); -+ ion_buffer_add(dev, buffer); -+ mutex_unlock(&dev->buffer_lock); -+ return buffer; -+ -+err1: -+ heap->ops->free(buffer); -+err2: -+ kfree(buffer); -+ return ERR_PTR(ret); -+} -+ -+struct ion_buffer *ion_buffer_alloc(struct ion_device *dev, size_t len, -+ unsigned int heap_id_mask, -+ unsigned int flags) -+{ -+ struct ion_buffer *buffer = NULL; -+ struct ion_heap *heap; -+ -+ if (!dev || !len) { -+ return ERR_PTR(-EINVAL); -+ } -+ -+ /* -+ * traverse the list of heaps available in this system in priority -+ * order. If the heap type is supported by the client, and matches the -+ * request of the caller allocate from it. Repeat until allocate has -+ * succeeded or all heaps have been tried -+ */ -+ len = PAGE_ALIGN(len); -+ if (!len) -+ return ERR_PTR(-EINVAL); -+ -+ down_read(&dev->lock); -+ plist_for_each_entry(heap, &dev->heaps, node) { -+ /* if the caller didn't specify this heap id */ -+ if (!((1 << heap->id) & heap_id_mask)) -+ continue; -+ buffer = ion_buffer_create(heap, dev, len, flags); -+ if (!IS_ERR(buffer)) -+ break; -+ } -+ up_read(&dev->lock); -+ -+ if (!buffer) -+ return ERR_PTR(-ENODEV); -+ -+ if (IS_ERR(buffer)) -+ return ERR_CAST(buffer); -+ -+ return buffer; -+} -+ -+void ion_buffer_release(struct ion_buffer *buffer) -+{ -+ if (buffer->kmap_cnt > 0) { -+ pr_warn_once("%s: buffer still mapped in the kernel\n", -+ __func__); -+ buffer->heap->ops->unmap_kernel(buffer->heap, buffer); -+ } -+ buffer->heap->ops->free(buffer); -+ spin_lock(&buffer->heap->stat_lock); -+ buffer->heap->num_of_buffers--; -+ buffer->heap->num_of_alloc_bytes -= buffer->size; -+ spin_unlock(&buffer->heap->stat_lock); -+ -+ kfree(buffer); -+} -+ -+void ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer) -+{ -+ struct ion_heap *heap; -+ -+ if (!dev || !buffer) { -+ pr_warn("%s: invalid argument\n", __func__); -+ return; -+ } -+ -+ heap = buffer->heap; -+ mutex_lock(&dev->buffer_lock); -+ rb_erase(&buffer->node, &dev->buffers); -+ mutex_unlock(&dev->buffer_lock); -+ -+ if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) -+ ion_heap_freelist_add(heap, buffer); -+ else -+ ion_buffer_release(buffer); -+} -+ -+void *ion_buffer_kmap_get(struct ion_buffer *buffer) -+{ -+ void *vaddr; -+ -+ if (buffer->kmap_cnt) { -+ buffer->kmap_cnt++; -+ return buffer->vaddr; -+ } -+ vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); -+ if (WARN_ONCE(!vaddr, -+ "heap->ops->map_kernel should return ERR_PTR on error")) -+ return ERR_PTR(-EINVAL); -+ if (IS_ERR(vaddr)) -+ return vaddr; -+ buffer->vaddr = vaddr; -+ buffer->kmap_cnt++; -+ return vaddr; -+} -+ -+void ion_buffer_kmap_put(struct ion_buffer *buffer) -+{ -+ buffer->kmap_cnt--; -+ if (!buffer->kmap_cnt) { -+ buffer->heap->ops->unmap_kernel(buffer->heap, buffer); -+ buffer->vaddr = NULL; -+ } -+} -diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c -index 473b465724f1..3b4f32b9cd2d 100644 ---- a/drivers/staging/android/ion/ion_heap.c -+++ b/drivers/staging/android/ion/ion_heap.c -@@ -15,7 +15,7 @@ - #include - #include - --#include "ion.h" -+#include "ion_private.h" - - void *ion_heap_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -@@ -198,7 +198,7 @@ static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, - buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; - total_drained += buffer->size; - spin_unlock(&heap->free_lock); -- ion_buffer_destroy(buffer); -+ ion_buffer_release(buffer); - spin_lock(&heap->free_lock); - } - spin_unlock(&heap->free_lock); -@@ -236,7 +236,7 @@ static int ion_heap_deferred_free(void *data) - list_del(&buffer->list); - heap->free_list_size -= buffer->size; - spin_unlock(&heap->free_lock); -- ion_buffer_destroy(buffer); -+ ion_buffer_release(buffer); - } - - return 0; -diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h -new file mode 100644 -index 000000000000..e80692c885b4 ---- /dev/null -+++ b/drivers/staging/android/ion/ion_private.h -@@ -0,0 +1,47 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * ION Memory Allocator - Internal header -+ * -+ * Copyright (C) 2019 Google, Inc. -+ */ -+ -+#ifndef _ION_PRIVATE_H -+#define _ION_PRIVATE_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ion.h" -+ -+/** -+ * struct ion_device - the metadata of the ion device node -+ * @dev: the actual misc device -+ * @buffers: an rb tree of all the existing buffers -+ * @buffer_lock: lock protecting the tree of buffers -+ * @lock: rwsem protecting the tree of heaps and clients -+ */ -+struct ion_device { -+ struct miscdevice dev; -+ struct rb_root buffers; -+ struct mutex buffer_lock; -+ struct rw_semaphore lock; -+ struct plist_head heaps; -+ struct dentry *debug_root; -+ int heap_cnt; -+}; -+ -+/* ion_buffer manipulators */ -+extern struct ion_buffer *ion_buffer_alloc(struct ion_device *dev, size_t len, -+ unsigned int heap_id_mask, -+ unsigned int flags); -+extern void ion_buffer_release(struct ion_buffer *buffer); -+extern void ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer); -+extern void *ion_buffer_kmap_get(struct ion_buffer *buffer); -+extern void ion_buffer_kmap_put(struct ion_buffer *buffer); -+ -+#endif /* _ION_PRIVATE_H */ diff --git a/patches/ANDROID-staging-ion-refactor-ion-s-dmabuf-manipulators-into-a-separate-file.patch b/patches/ANDROID-staging-ion-refactor-ion-s-dmabuf-manipulators-into-a-separate-file.patch deleted file mode 100644 index d4666692f1757f5dcb08fef53870a0e2052f5611..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-refactor-ion-s-dmabuf-manipulators-into-a-separate-file.patch +++ /dev/null @@ -1,677 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Wed, 7 Aug 2019 15:01:24 -0700 -Subject: ANDROID: staging: ion: refactor ion's dmabuf manipulators into a - separate file. - -This patch is preparatory work for making ion heaps modular. The patch -itself doesn't make any significant changes except for re-organizing the -buffer manipulator functions in a single file. This will be helpful -later when we specifically export some of these functions to be used by -a heap module. - -Bug: 133508579 -Test: ion-unit-tests - -Change-Id: I52ecea78a179c936006a21beb7630009984cb22f -Co-developed-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/Makefile | 2 +- - drivers/staging/android/ion/ion.c | 254 +--------------------- - drivers/staging/android/ion/ion_buffer.c | 6 +- - drivers/staging/android/ion/ion_dma_buf.c | 252 +++++++++++++++++++++ - drivers/staging/android/ion/ion_private.h | 11 +- - include/linux/ion.h | 16 +- - 6 files changed, 289 insertions(+), 252 deletions(-) - create mode 100644 drivers/staging/android/ion/ion_dma_buf.c - -diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile -index da386dbf3ffd..b6fab2816781 100644 ---- a/drivers/staging/android/ion/Makefile -+++ b/drivers/staging/android/ion/Makefile -@@ -1,4 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0 --obj-$(CONFIG_ION) += ion.o ion_buffer.o ion_heap.o -+obj-$(CONFIG_ION) += ion.o ion_buffer.o ion_dma_buf.o ion_heap.o - obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o - obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index 19d3e82b2f5b..c80a31da371b 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -17,276 +17,38 @@ - #include - #include - #include --#include - #include - #include - #include - #include - #include - #include --#include - - #include "ion_private.h" - - static struct ion_device *internal_dev; - static int heap_id; - --static struct sg_table *dup_sg_table(struct sg_table *table) --{ -- struct sg_table *new_table; -- int ret, i; -- struct scatterlist *sg, *new_sg; -- -- new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); -- if (!new_table) -- return ERR_PTR(-ENOMEM); -- -- ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL); -- if (ret) { -- kfree(new_table); -- return ERR_PTR(-ENOMEM); -- } -- -- new_sg = new_table->sgl; -- for_each_sg(table->sgl, sg, table->nents, i) { -- memcpy(new_sg, sg, sizeof(*sg)); -- new_sg->dma_address = 0; -- new_sg = sg_next(new_sg); -- } -- -- return new_table; --} -- --static void free_duped_table(struct sg_table *table) --{ -- sg_free_table(table); -- kfree(table); --} -- --struct ion_dma_buf_attachment { -- struct device *dev; -- struct sg_table *table; -- struct list_head list; --}; -- --static int ion_dma_buf_attach(struct dma_buf *dmabuf, -- struct dma_buf_attachment *attachment) --{ -- struct ion_dma_buf_attachment *a; -- struct sg_table *table; -- struct ion_buffer *buffer = dmabuf->priv; -- -- a = kzalloc(sizeof(*a), GFP_KERNEL); -- if (!a) -- return -ENOMEM; -- -- table = dup_sg_table(buffer->sg_table); -- if (IS_ERR(table)) { -- kfree(a); -- return -ENOMEM; -- } -- -- a->table = table; -- a->dev = attachment->dev; -- INIT_LIST_HEAD(&a->list); -- -- attachment->priv = a; -- -- mutex_lock(&buffer->lock); -- list_add(&a->list, &buffer->attachments); -- mutex_unlock(&buffer->lock); -- -- return 0; --} -- --static void ion_dma_buf_detatch(struct dma_buf *dmabuf, -- struct dma_buf_attachment *attachment) --{ -- struct ion_dma_buf_attachment *a = attachment->priv; -- struct ion_buffer *buffer = dmabuf->priv; -- -- mutex_lock(&buffer->lock); -- list_del(&a->list); -- mutex_unlock(&buffer->lock); -- free_duped_table(a->table); -- -- kfree(a); --} -- --static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, -- enum dma_data_direction direction) --{ -- struct ion_dma_buf_attachment *a = attachment->priv; -- struct sg_table *table; -- -- table = a->table; -- -- if (!dma_map_sg(attachment->dev, table->sgl, table->nents, -- direction)) -- return ERR_PTR(-ENOMEM); -- -- return table; --} -- --static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, -- struct sg_table *table, -- enum dma_data_direction direction) --{ -- dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction); --} -- --static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) --{ -- struct ion_buffer *buffer = dmabuf->priv; -- int ret = 0; -- -- if (!buffer->heap->ops->map_user) { -- pr_err("%s: this heap does not define a method for mapping to userspace\n", -- __func__); -- return -EINVAL; -- } -- -- if (!(buffer->flags & ION_FLAG_CACHED)) -- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -- -- mutex_lock(&buffer->lock); -- /* now map it to userspace */ -- ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); -- mutex_unlock(&buffer->lock); -- -- if (ret) -- pr_err("%s: failure mapping buffer to userspace\n", -- __func__); -- -- return ret; --} -- --static void ion_dma_buf_release(struct dma_buf *dmabuf) --{ -- struct ion_buffer *buffer = dmabuf->priv; -- -- ion_buffer_destroy(internal_dev, buffer); --} -- --static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) --{ -- struct ion_buffer *buffer = dmabuf->priv; -- -- return buffer->vaddr + offset * PAGE_SIZE; --} -- --static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset, -- void *ptr) --{ --} -- --static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, -- enum dma_data_direction direction) --{ -- struct ion_buffer *buffer = dmabuf->priv; -- void *vaddr; -- struct ion_dma_buf_attachment *a; -- int ret = 0; -- -- /* -- * TODO: Move this elsewhere because we don't always need a vaddr -- */ -- if (buffer->heap->ops->map_kernel) { -- mutex_lock(&buffer->lock); -- vaddr = ion_buffer_kmap_get(buffer); -- if (IS_ERR(vaddr)) { -- ret = PTR_ERR(vaddr); -- goto unlock; -- } -- mutex_unlock(&buffer->lock); -- } -- -- mutex_lock(&buffer->lock); -- list_for_each_entry(a, &buffer->attachments, list) { -- dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents, -- direction); -- } -- --unlock: -- mutex_unlock(&buffer->lock); -- return ret; --} -- --static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, -- enum dma_data_direction direction) --{ -- struct ion_buffer *buffer = dmabuf->priv; -- struct ion_dma_buf_attachment *a; -- -- if (buffer->heap->ops->map_kernel) { -- mutex_lock(&buffer->lock); -- ion_buffer_kmap_put(buffer); -- mutex_unlock(&buffer->lock); -- } -- -- mutex_lock(&buffer->lock); -- list_for_each_entry(a, &buffer->attachments, list) { -- dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents, -- direction); -- } -- mutex_unlock(&buffer->lock); -- -- return 0; --} -- --static const struct dma_buf_ops dma_buf_ops = { -- .map_dma_buf = ion_map_dma_buf, -- .unmap_dma_buf = ion_unmap_dma_buf, -- .mmap = ion_mmap, -- .release = ion_dma_buf_release, -- .attach = ion_dma_buf_attach, -- .detach = ion_dma_buf_detatch, -- .begin_cpu_access = ion_dma_buf_begin_cpu_access, -- .end_cpu_access = ion_dma_buf_end_cpu_access, -- .map = ion_dma_buf_kmap, -- .unmap = ion_dma_buf_kunmap, --}; -- --static struct dma_buf *ion_alloc_dmabuf(size_t len, unsigned int heap_id_mask, -- unsigned int flags) --{ -- struct ion_buffer *buffer; -- DEFINE_DMA_BUF_EXPORT_INFO(exp_info); -- struct dma_buf *dmabuf; -- -- pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, -- len, heap_id_mask, flags); -- -- buffer = ion_buffer_alloc(internal_dev, len, heap_id_mask, flags); -- if (IS_ERR(buffer)) -- return ERR_CAST(buffer); -- -- exp_info.ops = &dma_buf_ops; -- exp_info.size = buffer->size; -- exp_info.flags = O_RDWR; -- exp_info.priv = buffer; -- -- dmabuf = dma_buf_export(&exp_info); -- if (IS_ERR(dmabuf)) -- ion_buffer_destroy(internal_dev, buffer); -- -- return dmabuf; --} -- -+/* Entry into ION allocator for rest of the kernel */ - struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - unsigned int flags) - { -- return ion_alloc_dmabuf(len, heap_id_mask, flags); -+ return ion_dmabuf_alloc(internal_dev, len, heap_id_mask, flags); - } - EXPORT_SYMBOL_GPL(ion_alloc); - -+int ion_free(struct ion_buffer *buffer) -+{ -+ return ion_buffer_destroy(internal_dev, buffer); -+} -+ - static int ion_alloc_fd(size_t len, unsigned int heap_id_mask, - unsigned int flags) - { - int fd; - struct dma_buf *dmabuf; - -- dmabuf = ion_alloc_dmabuf(len, heap_id_mask, flags); -+ dmabuf = ion_dmabuf_alloc(internal_dev, len, heap_id_mask, flags); - if (IS_ERR(dmabuf)) - return PTR_ERR(dmabuf); - -diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c -index 8b8dd1e216d4..c10ea6672f1a 100644 ---- a/drivers/staging/android/ion/ion_buffer.c -+++ b/drivers/staging/android/ion/ion_buffer.c -@@ -149,13 +149,13 @@ void ion_buffer_release(struct ion_buffer *buffer) - kfree(buffer); - } - --void ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer) -+int ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer) - { - struct ion_heap *heap; - - if (!dev || !buffer) { - pr_warn("%s: invalid argument\n", __func__); -- return; -+ return -EINVAL; - } - - heap = buffer->heap; -@@ -167,6 +167,8 @@ void ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer) - ion_heap_freelist_add(heap, buffer); - else - ion_buffer_release(buffer); -+ -+ return 0; - } - - void *ion_buffer_kmap_get(struct ion_buffer *buffer) -diff --git a/drivers/staging/android/ion/ion_dma_buf.c b/drivers/staging/android/ion/ion_dma_buf.c -new file mode 100644 -index 000000000000..0de08e6f1af5 ---- /dev/null -+++ b/drivers/staging/android/ion/ion_dma_buf.c -@@ -0,0 +1,252 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * ION Memory Allocator - dmabuf interface -+ * -+ * Copyright (c) 2019, Google, Inc. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ion_private.h" -+ -+static struct sg_table *dup_sg_table(struct sg_table *table) -+{ -+ struct sg_table *new_table; -+ int ret, i; -+ struct scatterlist *sg, *new_sg; -+ -+ new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); -+ if (!new_table) -+ return ERR_PTR(-ENOMEM); -+ -+ ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL); -+ if (ret) { -+ kfree(new_table); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ new_sg = new_table->sgl; -+ for_each_sg(table->sgl, sg, table->nents, i) { -+ memcpy(new_sg, sg, sizeof(*sg)); -+ new_sg->dma_address = 0; -+ new_sg = sg_next(new_sg); -+ } -+ -+ return new_table; -+} -+ -+static void free_duped_table(struct sg_table *table) -+{ -+ sg_free_table(table); -+ kfree(table); -+} -+ -+struct ion_dma_buf_attachment { -+ struct device *dev; -+ struct sg_table *table; -+ struct list_head list; -+}; -+ -+static int ion_dma_buf_attach(struct dma_buf *dmabuf, -+ struct dma_buf_attachment *attachment) -+{ -+ struct ion_dma_buf_attachment *a; -+ struct sg_table *table; -+ struct ion_buffer *buffer = dmabuf->priv; -+ -+ a = kzalloc(sizeof(*a), GFP_KERNEL); -+ if (!a) -+ return -ENOMEM; -+ -+ table = dup_sg_table(buffer->sg_table); -+ if (IS_ERR(table)) { -+ kfree(a); -+ return -ENOMEM; -+ } -+ -+ a->table = table; -+ a->dev = attachment->dev; -+ INIT_LIST_HEAD(&a->list); -+ -+ attachment->priv = a; -+ -+ mutex_lock(&buffer->lock); -+ list_add(&a->list, &buffer->attachments); -+ mutex_unlock(&buffer->lock); -+ -+ return 0; -+} -+ -+static void ion_dma_buf_detatch(struct dma_buf *dmabuf, -+ struct dma_buf_attachment *attachment) -+{ -+ struct ion_dma_buf_attachment *a = attachment->priv; -+ struct ion_buffer *buffer = dmabuf->priv; -+ -+ mutex_lock(&buffer->lock); -+ list_del(&a->list); -+ mutex_unlock(&buffer->lock); -+ free_duped_table(a->table); -+ -+ kfree(a); -+} -+ -+static struct sg_table *ion_dma_buf_map(struct dma_buf_attachment *attachment, -+ enum dma_data_direction direction) -+{ -+ struct ion_dma_buf_attachment *a = attachment->priv; -+ struct sg_table *table; -+ -+ table = a->table; -+ -+ if (!dma_map_sg(attachment->dev, table->sgl, table->nents, -+ direction)) -+ return ERR_PTR(-ENOMEM); -+ -+ return table; -+} -+ -+static void ion_dma_buf_unmap(struct dma_buf_attachment *attachment, -+ struct sg_table *table, -+ enum dma_data_direction direction) -+{ -+ dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction); -+} -+ -+static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ int ret = 0; -+ -+ if (!buffer->heap->ops->map_user) { -+ pr_err("%s: this heap does not define a method for mapping to userspace\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if (!(buffer->flags & ION_FLAG_CACHED)) -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ -+ mutex_lock(&buffer->lock); -+ /* now map it to userspace */ -+ ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); -+ mutex_unlock(&buffer->lock); -+ -+ if (ret) -+ pr_err("%s: failure mapping buffer to userspace\n", -+ __func__); -+ -+ return ret; -+} -+ -+static void ion_dma_buf_release(struct dma_buf *dmabuf) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ -+ ion_free(buffer); -+} -+ -+static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ -+ return buffer->vaddr + offset * PAGE_SIZE; -+} -+ -+static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, -+ enum dma_data_direction direction) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ void *vaddr; -+ struct ion_dma_buf_attachment *a; -+ int ret = 0; -+ -+ /* -+ * TODO: Move this elsewhere because we don't always need a vaddr -+ */ -+ if (buffer->heap->ops->map_kernel) { -+ mutex_lock(&buffer->lock); -+ vaddr = ion_buffer_kmap_get(buffer); -+ if (IS_ERR(vaddr)) { -+ ret = PTR_ERR(vaddr); -+ goto unlock; -+ } -+ mutex_unlock(&buffer->lock); -+ } -+ -+ mutex_lock(&buffer->lock); -+ list_for_each_entry(a, &buffer->attachments, list) { -+ dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents, -+ direction); -+ } -+ -+unlock: -+ mutex_unlock(&buffer->lock); -+ return ret; -+} -+ -+static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, -+ enum dma_data_direction direction) -+{ -+ struct ion_buffer *buffer = dmabuf->priv; -+ struct ion_dma_buf_attachment *a; -+ -+ if (buffer->heap->ops->map_kernel) { -+ mutex_lock(&buffer->lock); -+ ion_buffer_kmap_put(buffer); -+ mutex_unlock(&buffer->lock); -+ } -+ -+ mutex_lock(&buffer->lock); -+ list_for_each_entry(a, &buffer->attachments, list) { -+ dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents, -+ direction); -+ } -+ mutex_unlock(&buffer->lock); -+ -+ return 0; -+} -+ -+static const struct dma_buf_ops dma_buf_ops = { -+ .map_dma_buf = ion_dma_buf_map, -+ .unmap_dma_buf = ion_dma_buf_unmap, -+ .mmap = ion_dma_buf_mmap, -+ .release = ion_dma_buf_release, -+ .attach = ion_dma_buf_attach, -+ .detach = ion_dma_buf_detatch, -+ .begin_cpu_access = ion_dma_buf_begin_cpu_access, -+ .end_cpu_access = ion_dma_buf_end_cpu_access, -+ .map = ion_dma_buf_kmap, -+}; -+ -+struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, -+ unsigned int heap_id_mask, -+ unsigned int flags) -+{ -+ struct ion_buffer *buffer; -+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info); -+ struct dma_buf *dmabuf; -+ -+ pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, -+ len, heap_id_mask, flags); -+ -+ buffer = ion_buffer_alloc(dev, len, heap_id_mask, flags); -+ if (IS_ERR(buffer)) -+ return ERR_CAST(buffer); -+ -+ exp_info.ops = &dma_buf_ops; -+ exp_info.size = buffer->size; -+ exp_info.flags = O_RDWR; -+ exp_info.priv = buffer; -+ -+ dmabuf = dma_buf_export(&exp_info); -+ if (IS_ERR(dmabuf)) -+ ion_buffer_destroy(dev, buffer); -+ -+ return dmabuf; -+} -diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h -index e80692c885b4..b3c8b55788db 100644 ---- a/drivers/staging/android/ion/ion_private.h -+++ b/drivers/staging/android/ion/ion_private.h -@@ -9,6 +9,7 @@ - #define _ION_PRIVATE_H - - #include -+#include - #include - #include - #include -@@ -40,8 +41,16 @@ extern struct ion_buffer *ion_buffer_alloc(struct ion_device *dev, size_t len, - unsigned int heap_id_mask, - unsigned int flags); - extern void ion_buffer_release(struct ion_buffer *buffer); --extern void ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer); -+extern int ion_buffer_destroy(struct ion_device *dev, -+ struct ion_buffer *buffer); - extern void *ion_buffer_kmap_get(struct ion_buffer *buffer); - extern void ion_buffer_kmap_put(struct ion_buffer *buffer); - -+/* ion dmabuf allocator */ -+extern struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, -+ unsigned int heap_id_mask, -+ unsigned int flags); -+extern int ion_free(struct ion_buffer *buffer); -+ -+ - #endif /* _ION_PRIVATE_H */ -diff --git a/include/linux/ion.h b/include/linux/ion.h -index 7bec77d98224..66a694b875ca 100644 ---- a/include/linux/ion.h -+++ b/include/linux/ion.h -@@ -10,8 +10,18 @@ - #include - - #ifdef CONFIG_ION --/* -- * Allocates an ION buffer. -+ -+ -+/** -+ * ion_alloc - Allocates an ion buffer of given size from given heap -+ * -+ * @len: size of the buffer to be allocated. -+ * @heap_id_mask: a bitwise maks of heap ids to allocate from -+ * @flags: ION_BUFFER_XXXX flags for the new buffer. -+ * -+ * The function exports a dma_buf object for the new ion buffer internally -+ * and returns that to the caller. So, the buffer is ready to be used by other -+ * drivers immediately. Returns ERR_PTR in case of failure. - */ - struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - unsigned int flags); -@@ -22,5 +32,7 @@ static inline struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - { - return ERR_PTR(-ENOMEM); - } -+ -+ - #endif /* CONFIG_ION */ - #endif /* _ION_KERNEL_H */ diff --git a/patches/ANDROID-staging-ion-refactor-ion-s-heap-API-into-linux-ion.h.patch b/patches/ANDROID-staging-ion-refactor-ion-s-heap-API-into-linux-ion.h.patch deleted file mode 100644 index 00a9df0371e5876d5cb11d8533f96d2e64ea5fcd..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-refactor-ion-s-heap-API-into-linux-ion.h.patch +++ /dev/null @@ -1,871 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Thu, 8 Aug 2019 08:35:46 -0700 -Subject: ANDROID: staging: ion: refactor ion's heap API into linux/ion.h - -Now that we know the APIs needed by system and cma heaps, -refactor and move all those into linux/ion.h. - -Unfortunately, the UAPI of ion is now split into linux/ion.h -and drivers/staging/android/uapi/ion.h since some of the UAPI -leaks into heap implementation (ion flags). It can all be moved -into linux/ion.h eventually for all android kernels. - -Bug: 133508579 -Test: ion-unit-tests - -Change-Id: I73ea59b410c46a02e23f2da5c6bdc15182a50b32 -Co-developed-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - .../staging/android/ion/heaps/ion_cma_heap.c | 3 +- - .../android/ion/heaps/ion_system_heap.c | 2 +- - drivers/staging/android/ion/ion.c | 1 - - drivers/staging/android/ion/ion.h | 246 -------------- - drivers/staging/android/ion/ion_buffer.c | 37 ++- - drivers/staging/android/ion/ion_heap.c | 44 --- - drivers/staging/android/ion/ion_private.h | 3 +- - include/linux/ion.h | 312 +++++++++++++++++- - .../staging/android => include}/uapi/ion.h | 35 +- - 9 files changed, 367 insertions(+), 316 deletions(-) - delete mode 100644 drivers/staging/android/ion/ion.h - rename {drivers/staging/android => include}/uapi/ion.h (74%) - -diff --git a/drivers/staging/android/ion/heaps/ion_cma_heap.c b/drivers/staging/android/ion/heaps/ion_cma_heap.c -index 0872e5d630f8..83f7dce74f18 100644 ---- a/drivers/staging/android/ion/heaps/ion_cma_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_cma_heap.c -@@ -7,6 +7,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -14,8 +15,6 @@ - #include - #include - --#include "../ion.h" -- - struct ion_cma_heap { - struct ion_heap heap; - struct cma *cma; -diff --git a/drivers/staging/android/ion/heaps/ion_system_heap.c b/drivers/staging/android/ion/heaps/ion_system_heap.c -index 8e26016082d4..afb2a6385705 100644 ---- a/drivers/staging/android/ion/heaps/ion_system_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_heap.c -@@ -9,12 +9,12 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - --#include "../ion.h" - #include "ion_page_pool.h" - - #define NUM_ORDERS ARRAY_SIZE(orders) -diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c -index c80a31da371b..b862bdfeca89 100644 ---- a/drivers/staging/android/ion/ion.c -+++ b/drivers/staging/android/ion/ion.c -@@ -246,7 +246,6 @@ void ion_device_add_heap(struct ion_heap *heap) - pr_err("%s: Failed to register shrinker\n", __func__); - } - -- heap->dev = dev; - heap->num_of_buffers = 0; - heap->num_of_alloc_bytes = 0; - heap->alloc_bytes_wm = 0; -diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h -deleted file mode 100644 -index b5b5412507fd..000000000000 ---- a/drivers/staging/android/ion/ion.h -+++ /dev/null -@@ -1,246 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0 */ --/* -- * ION Memory Allocator kernel interface header -- * -- * Copyright (C) 2011 Google, Inc. -- */ -- --#ifndef _ION_H --#define _ION_H -- --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "../uapi/ion.h" -- --/** -- * struct ion_buffer - metadata for a particular buffer -- * @list: element in list of deferred freeable buffers -- * @dev: back pointer to the ion_device -- * @heap: back pointer to the heap the buffer came from -- * @flags: buffer specific flags -- * @private_flags: internal buffer specific flags -- * @size: size of the buffer -- * @priv_virt: private data to the buffer representable as -- * a void * -- * @lock: protects the buffers cnt fields -- * @kmap_cnt: number of times the buffer is mapped to the kernel -- * @vaddr: the kernel mapping if kmap_cnt is not zero -- * @sg_table: the sg table for the buffer -- * @attachments: list of devices attached to this buffer -- */ --struct ion_buffer { -- struct list_head list; -- struct ion_heap *heap; -- unsigned long flags; -- unsigned long private_flags; -- size_t size; -- void *priv_virt; -- struct mutex lock; -- int kmap_cnt; -- void *vaddr; -- struct sg_table *sg_table; -- struct list_head attachments; --}; -- --void ion_buffer_destroy(struct ion_buffer *buffer); -- --/** -- * struct ion_heap_ops - ops to operate on a given heap -- * @allocate: allocate memory -- * @free: free memory -- * @map_kernel map memory to the kernel -- * @unmap_kernel unmap memory to the kernel -- * @map_user map memory to userspace -- * -- * allocate, phys, and map_user return 0 on success, -errno on error. -- * map_dma and map_kernel return pointer on success, ERR_PTR on -- * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in -- * the buffer's private_flags when called from a shrinker. In that -- * case, the pages being free'd must be truly free'd back to the -- * system, not put in a page pool or otherwise cached. -- */ --struct ion_heap_ops { -- int (*allocate)(struct ion_heap *heap, -- struct ion_buffer *buffer, unsigned long len, -- unsigned long flags); -- void (*free)(struct ion_buffer *buffer); -- void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); -- void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); -- int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, -- struct vm_area_struct *vma); -- int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); --}; -- --/** -- * heap flags - flags between the heaps and core ion code -- */ --#define ION_HEAP_FLAG_DEFER_FREE BIT(0) -- --/** -- * private flags - flags internal to ion -- */ --/* -- * Buffer is being freed from a shrinker function. Skip any possible -- * heap-specific caching mechanism (e.g. page pools). Guarantees that -- * any buffer storage that came from the system allocator will be -- * returned to the system allocator. -- */ --#define ION_PRIV_FLAG_SHRINKER_FREE BIT(0) -- --/** -- * struct ion_heap - represents a heap in the system -- * @node: rb node to put the heap on the device's tree of heaps -- * @dev: back pointer to the ion_device -- * @type: type of heap -- * @ops: ops struct as above -- * @flags: flags -- * @id: id of heap, also indicates priority of this heap when -- * allocating. These are specified by platform data and -- * MUST be unique -- * @name: used for debugging -- * @shrinker: a shrinker for the heap -- * @free_list: free list head if deferred free is used -- * @free_list_size size of the deferred free list in bytes -- * @lock: protects the free list -- * @waitqueue: queue to wait on from deferred free thread -- * @task: task struct of deferred free thread -- * @num_of_buffers the number of currently allocated buffers -- * @num_of_alloc_bytes the number of allocated bytes -- * @alloc_bytes_wm the number of allocated bytes watermark -- * -- * Represents a pool of memory from which buffers can be made. In some -- * systems the only heap is regular system memory allocated via vmalloc. -- * On others, some blocks might require large physically contiguous buffers -- * that are allocated from a specially reserved heap. -- */ --struct ion_heap { -- struct plist_node node; -- struct ion_device *dev; -- enum ion_heap_type type; -- struct ion_heap_ops *ops; -- unsigned long flags; -- unsigned int id; -- const char *name; -- -- /* deferred free support */ -- struct shrinker shrinker; -- struct list_head free_list; -- size_t free_list_size; -- spinlock_t free_lock; -- wait_queue_head_t waitqueue; -- struct task_struct *task; -- -- /* heap statistics */ -- u64 num_of_buffers; -- u64 num_of_alloc_bytes; -- u64 alloc_bytes_wm; -- -- /* protect heap statistics */ -- spinlock_t stat_lock; --}; -- --/** -- * ion_device_add_heap - adds a heap to the ion device -- * @heap: the heap to add -- */ --void ion_device_add_heap(struct ion_heap *heap); -- --/* ion_buffer_zero - zeroes out an ion buffer respecting the ION_FLAGs. -- * -- * @buffer: ion_buffer to zero -- * -- * Returns 0 on success, negative error otherwise. -- */ --int ion_buffer_zero(struct ion_buffer *buffer); -- --/** -- * some helpers for common operations on buffers using the sg_table -- * and vaddr fields -- */ --void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer); --void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer); --int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, -- struct vm_area_struct *vma); --int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); --int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, -- pgprot_t pgprot); -- --/** -- * ion_heap_init_shrinker -- * @heap: the heap -- * -- * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op -- * this function will be called to setup a shrinker to shrink the freelists -- * and call the heap's shrink op. -- */ --int ion_heap_init_shrinker(struct ion_heap *heap); -- --/** -- * ion_heap_init_deferred_free -- initialize deferred free functionality -- * @heap: the heap -- * -- * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag this function will -- * be called to setup deferred frees. Calls to free the buffer will -- * return immediately and the actual free will occur some time later -- */ --int ion_heap_init_deferred_free(struct ion_heap *heap); -- --/** -- * ion_heap_freelist_add - add a buffer to the deferred free list -- * @heap: the heap -- * @buffer: the buffer -- * -- * Adds an item to the deferred freelist. -- */ --void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer); -- --/** -- * ion_heap_freelist_drain - drain the deferred free list -- * @heap: the heap -- * @size: amount of memory to drain in bytes -- * -- * Drains the indicated amount of memory from the deferred freelist immediately. -- * Returns the total amount freed. The total freed may be higher depending -- * on the size of the items in the list, or lower if there is insufficient -- * total memory on the freelist. -- */ --size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size); -- --/** -- * ion_heap_freelist_shrink - drain the deferred free -- * list, skipping any heap-specific -- * pooling or caching mechanisms -- * -- * @heap: the heap -- * @size: amount of memory to drain in bytes -- * -- * Drains the indicated amount of memory from the deferred freelist immediately. -- * Returns the total amount freed. The total freed may be higher depending -- * on the size of the items in the list, or lower if there is insufficient -- * total memory on the freelist. -- * -- * Unlike with @ion_heap_freelist_drain, don't put any pages back into -- * page pools or otherwise cache the pages. Everything must be -- * genuinely free'd back to the system. If you're free'ing from a -- * shrinker you probably want to use this. Note that this relies on -- * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE -- * flag. -- */ --size_t ion_heap_freelist_shrink(struct ion_heap *heap, -- size_t size); -- --/** -- * ion_heap_freelist_size - returns the size of the freelist in bytes -- * @heap: the heap -- */ --size_t ion_heap_freelist_size(struct ion_heap *heap); -- --#endif /* _ION_H */ -diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c -index 50c2dbc3ebec..adce2d489f56 100644 ---- a/drivers/staging/android/ion/ion_buffer.c -+++ b/drivers/staging/android/ion/ion_buffer.c -@@ -92,6 +92,41 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, - return ERR_PTR(ret); - } - -+static int ion_clear_pages(struct page **pages, int num, pgprot_t pgprot) -+{ -+ void *addr = vm_map_ram(pages, num, -1, pgprot); -+ -+ if (!addr) -+ return -ENOMEM; -+ memset(addr, 0, PAGE_SIZE * num); -+ vm_unmap_ram(addr, num); -+ -+ return 0; -+} -+ -+static int ion_sglist_zero(struct scatterlist *sgl, unsigned int nents, -+ pgprot_t pgprot) -+{ -+ int p = 0; -+ int ret = 0; -+ struct sg_page_iter piter; -+ struct page *pages[32]; -+ -+ for_each_sg_page(sgl, &piter, nents, 0) { -+ pages[p++] = sg_page_iter_page(&piter); -+ if (p == ARRAY_SIZE(pages)) { -+ ret = ion_clear_pages(pages, p, pgprot); -+ if (ret) -+ return ret; -+ p = 0; -+ } -+ } -+ if (p) -+ ret = ion_clear_pages(pages, p, pgprot); -+ -+ return ret; -+} -+ - struct ion_buffer *ion_buffer_alloc(struct ion_device *dev, size_t len, - unsigned int heap_id_mask, - unsigned int flags) -@@ -147,7 +182,7 @@ int ion_buffer_zero(struct ion_buffer *buffer) - else - pgprot = pgprot_writecombine(PAGE_KERNEL); - -- return ion_heap_sglist_zero(table->sgl, table->nents, pgprot); -+ return ion_sglist_zero(table->sgl, table->nents, pgprot); - } - - void ion_buffer_release(struct ion_buffer *buffer) -diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c -index 39eb60e4842e..755548a4382d 100644 ---- a/drivers/staging/android/ion/ion_heap.c -+++ b/drivers/staging/android/ion/ion_heap.c -@@ -61,18 +61,6 @@ static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, - return freed; - } - --static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) --{ -- void *addr = vm_map_ram(pages, num, -1, pgprot); -- -- if (!addr) -- return -ENOMEM; -- memset(addr, 0, PAGE_SIZE * num); -- vm_unmap_ram(addr, num); -- -- return 0; --} -- - static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, - bool skip_pools) - { -@@ -211,38 +199,6 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - return 0; - } - --int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, -- pgprot_t pgprot) --{ -- int p = 0; -- int ret = 0; -- struct sg_page_iter piter; -- struct page *pages[32]; -- -- for_each_sg_page(sgl, &piter, nents, 0) { -- pages[p++] = sg_page_iter_page(&piter); -- if (p == ARRAY_SIZE(pages)) { -- ret = ion_heap_clear_pages(pages, p, pgprot); -- if (ret) -- return ret; -- p = 0; -- } -- } -- if (p) -- ret = ion_heap_clear_pages(pages, p, pgprot); -- -- return ret; --} -- --int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) --{ -- struct scatterlist sg; -- -- sg_init_table(&sg, 1); -- sg_set_page(&sg, page, size, 0); -- return ion_heap_sglist_zero(&sg, 1, pgprot); --} -- - void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer) - { - spin_lock(&heap->free_lock); -diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h -index 9c8f482cd9d2..ed7ed39d0df1 100644 ---- a/drivers/staging/android/ion/ion_private.h -+++ b/drivers/staging/android/ion/ion_private.h -@@ -10,6 +10,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -17,8 +18,6 @@ - #include - #include - --#include "ion.h" -- - /** - * struct ion_device - the metadata of the ion device node - * @dev: the actual misc device -diff --git a/include/linux/ion.h b/include/linux/ion.h -index 66a694b875ca..775e948a362c 100644 ---- a/include/linux/ion.h -+++ b/include/linux/ion.h -@@ -8,9 +8,264 @@ - - #include - #include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * struct ion_buffer - metadata for a particular buffer -+ * @node: node in the ion_device buffers tree -+ * @list: element in list of deferred freeable buffers -+ * @heap: back pointer to the heap the buffer came from -+ * @flags: buffer specific flags -+ * @private_flags: internal buffer specific flags -+ * @size: size of the buffer -+ * @priv_virt: private data to the buffer representable as -+ * a void * -+ * @lock: protects the buffers cnt fields -+ * @kmap_cnt: number of times the buffer is mapped to the kernel -+ * @vaddr: the kernel mapping if kmap_cnt is not zero -+ * @sg_table: the sg table for the buffer -+ * @attachments: list of devices attached to this buffer -+ */ -+struct ion_buffer { -+ union { -+ struct rb_node node; -+ struct list_head list; -+ }; -+ struct ion_heap *heap; -+ unsigned long flags; -+ unsigned long private_flags; -+ size_t size; -+ void *priv_virt; -+ struct mutex lock; -+ int kmap_cnt; -+ void *vaddr; -+ struct sg_table *sg_table; -+ struct list_head attachments; -+}; -+ -+/** -+ * struct ion_heap_ops - ops to operate on a given heap -+ * @allocate: allocate memory -+ * @free: free memory -+ * @map_kernel map memory to the kernel -+ * @unmap_kernel unmap memory to the kernel -+ * @map_user map memory to userspace -+ * -+ * allocate, phys, and map_user return 0 on success, -errno on error. -+ * map_dma and map_kernel return pointer on success, ERR_PTR on -+ * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in -+ * the buffer's private_flags when called from a shrinker. In that -+ * case, the pages being free'd must be truly free'd back to the -+ * system, not put in a page pool or otherwise cached. -+ */ -+struct ion_heap_ops { -+ int (*allocate)(struct ion_heap *heap, -+ struct ion_buffer *buffer, unsigned long len, -+ unsigned long flags); -+ void (*free)(struct ion_buffer *buffer); -+ void * (*map_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); -+ void (*unmap_kernel)(struct ion_heap *heap, struct ion_buffer *buffer); -+ int (*map_user)(struct ion_heap *mapper, struct ion_buffer *buffer, -+ struct vm_area_struct *vma); -+ int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); -+}; -+ -+/** -+ * heap flags - flags between the heaps and core ion code -+ */ -+#define ION_HEAP_FLAG_DEFER_FREE BIT(0) -+ -+/** -+ * private flags - flags internal to ion -+ */ -+/* -+ * Buffer is being freed from a shrinker function. Skip any possible -+ * heap-specific caching mechanism (e.g. page pools). Guarantees that -+ * any buffer storage that came from the system allocator will be -+ * returned to the system allocator. -+ */ -+#define ION_PRIV_FLAG_SHRINKER_FREE BIT(0) -+ -+/** -+ * struct ion_heap - represents a heap in the system -+ * @node: rb node to put the heap on the device's tree of heaps -+ * @type: type of heap -+ * @ops: ops struct as above -+ * @flags: flags -+ * @id: id of heap, also indicates priority of this heap when -+ * allocating. These are specified by platform data and -+ * MUST be unique -+ * @name: used for debugging -+ * @shrinker: a shrinker for the heap -+ * @free_list: free list head if deferred free is used -+ * @free_list_size size of the deferred free list in bytes -+ * @lock: protects the free list -+ * @waitqueue: queue to wait on from deferred free thread -+ * @task: task struct of deferred free thread -+ * @num_of_buffers the number of currently allocated buffers -+ * @num_of_alloc_bytes the number of allocated bytes -+ * @alloc_bytes_wm the number of allocated bytes watermark -+ * -+ * Represents a pool of memory from which buffers can be made. In some -+ * systems the only heap is regular system memory allocated via vmalloc. -+ * On others, some blocks might require large physically contiguous buffers -+ * that are allocated from a specially reserved heap. -+ */ -+struct ion_heap { -+ struct plist_node node; -+ enum ion_heap_type type; -+ struct ion_heap_ops *ops; -+ unsigned long flags; -+ unsigned int id; -+ const char *name; -+ -+ /* deferred free support */ -+ struct shrinker shrinker; -+ struct list_head free_list; -+ size_t free_list_size; -+ spinlock_t free_lock; -+ wait_queue_head_t waitqueue; -+ struct task_struct *task; -+ -+ /* heap statistics */ -+ u64 num_of_buffers; -+ u64 num_of_alloc_bytes; -+ u64 alloc_bytes_wm; -+ -+ /* protect heap statistics */ -+ spinlock_t stat_lock; -+}; - - #ifdef CONFIG_ION - -+/** -+ * ion_device_add_heap - adds a heap to the ion device -+ * -+ * @heap: the heap to add -+ */ -+void ion_device_add_heap(struct ion_heap *heap); -+ -+/** -+ * ion_heap_init_shrinker -+ * @heap: the heap -+ * -+ * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op -+ * this function will be called to setup a shrinker to shrink the freelists -+ * and call the heap's shrink op. -+ */ -+int ion_heap_init_shrinker(struct ion_heap *heap); -+ -+/** -+ * ion_heap_init_deferred_free -- initialize deferred free functionality -+ * @heap: the heap -+ * -+ * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag this function will -+ * be called to setup deferred frees. Calls to free the buffer will -+ * return immediately and the actual free will occur some time later -+ */ -+int ion_heap_init_deferred_free(struct ion_heap *heap); -+ -+/** -+ * ion_heap_freelist_add - add a buffer to the deferred free list -+ * @heap: the heap -+ * @buffer: the buffer -+ * -+ * Adds an item to the deferred freelist. -+ */ -+void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer); -+ -+/** -+ * ion_heap_freelist_drain - drain the deferred free list -+ * @heap: the heap -+ * @size: amount of memory to drain in bytes -+ * -+ * Drains the indicated amount of memory from the deferred freelist immediately. -+ * Returns the total amount freed. The total freed may be higher depending -+ * on the size of the items in the list, or lower if there is insufficient -+ * total memory on the freelist. -+ */ -+size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size); -+ -+/** -+ * ion_heap_freelist_shrink - drain the deferred free -+ * list, skipping any heap-specific -+ * pooling or caching mechanisms -+ * -+ * @heap: the heap -+ * @size: amount of memory to drain in bytes -+ * -+ * Drains the indicated amount of memory from the deferred freelist immediately. -+ * Returns the total amount freed. The total freed may be higher depending -+ * on the size of the items in the list, or lower if there is insufficient -+ * total memory on the freelist. -+ * -+ * Unlike with @ion_heap_freelist_drain, don't put any pages back into -+ * page pools or otherwise cache the pages. Everything must be -+ * genuinely free'd back to the system. If you're free'ing from a -+ * shrinker you probably want to use this. Note that this relies on -+ * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE -+ * flag. -+ */ -+size_t ion_heap_freelist_shrink(struct ion_heap *heap, -+ size_t size); -+ -+/** -+ * ion_heap_freelist_size - returns the size of the freelist in bytes -+ * @heap: the heap -+ */ -+size_t ion_heap_freelist_size(struct ion_heap *heap); -+ -+/** -+ * ion_heap_map_kernel - map the ion_buffer in kernel virtual address space. -+ * -+ * @heap: the heap -+ * @buffer: buffer to be mapped -+ * -+ * Maps the buffer using vmap(). The function respects cache flags for the -+ * buffer and creates the page table entries accordingly. Returns virtual -+ * address at the beginning of the buffer or ERR_PTR. -+ */ -+void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer); -+ -+/** -+ * ion_heap_unmap_kernel - unmap ion_buffer -+ * -+ * @buffer: buffer to be unmapped -+ * -+ * ION wrapper for vunmap() of the ion buffer. -+ */ -+void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer); -+ -+/** -+ * ion_heap_map_user - map given ion buffer in provided vma -+ * -+ * @heap: the heap this buffer belongs to -+ * @buffer: Ion buffer to be mapped -+ * @vma: vma of the process where buffer should be mapped. -+ * -+ * Maps the buffer using remap_pfn_range() into specific process's vma starting -+ * with vma->vm_start. The vma size is expected to be >= ion buffer size. -+ * If not, a partial buffer mapping may be created. Returns 0 on success. -+ */ -+int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, -+ struct vm_area_struct *vma); -+ -+/* ion_buffer_zero - zeroes out an ion buffer respecting the ION_FLAGs. -+ * -+ * @buffer: ion_buffer to zero -+ * -+ * Returns 0 on success, negative error otherwise. -+ */ -+int ion_buffer_zero(struct ion_buffer *buffer); - - /** - * ion_alloc - Allocates an ion buffer of given size from given heap -@@ -27,12 +282,67 @@ struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - unsigned int flags); - - #else -+ -+static inline int ion_device_add_heap(struct ion_heap *heap) -+{ -+ return -ENODEV; -+} -+ -+static inline int ion_heap_init_shrinker(struct ion_heap *heap) -+{ -+ return -ENODEV; -+} -+ -+static inline int ion_heap_init_deferred_free(struct ion_heap *heap) -+{ -+ return -ENODEV; -+} -+ -+static inline void ion_heap_freelist_add(struct ion_heap *heap, -+ struct ion_buffer *buffer) {} -+ -+static inline size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) -+{ -+ return -ENODEV; -+} -+ -+static inline size_t ion_heap_freelist_shrink(struct ion_heap *heap, -+ size_t size) -+{ -+ return -ENODEV; -+} -+ -+static inline size_t ion_heap_freelist_size(struct ion_heap *heap) -+{ -+ return -ENODEV; -+} -+ -+static inline void *ion_heap_map_kernel(struct ion_heap *heap, -+ struct ion_buffer *buffer) -+{ -+ return ERR_PTR(-ENODEV); -+} -+ -+static inline void ion_heap_unmap_kernel(struct ion_heap *heap, -+ struct ion_buffer *buffer) {} -+ -+static inline int ion_heap_map_user(struct ion_heap *heap, -+ struct ion_buffer *buffer, -+ struct vm_area_struct *vma) -+{ -+ return -ENODEV; -+} -+ -+static inline int ion_buffer_zero(struct ion_buffer *buffer) -+{ -+ return -EINVAL; -+} -+ - static inline struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, - unsigned int flags) - { - return ERR_PTR(-ENOMEM); - } - -- - #endif /* CONFIG_ION */ - #endif /* _ION_KERNEL_H */ -diff --git a/drivers/staging/android/uapi/ion.h b/include/uapi/ion.h -similarity index 74% -rename from drivers/staging/android/uapi/ion.h -rename to include/uapi/ion.h -index 46c93fcb46d6..bfcbc0e70921 100644 ---- a/drivers/staging/android/uapi/ion.h -+++ b/include/uapi/ion.h -@@ -13,26 +13,25 @@ - - /** - * enum ion_heap_types - list of all possible types of heaps -- * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc -+ * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc - * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc -- * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved -- * carveout heap, allocations are physically -- * contiguous -- * @ION_HEAP_TYPE_DMA: memory allocated via DMA API -- * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask -- * is used to identify the heaps, so only 32 -- * total heap types are supported -+ * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved -+ * carveout heap, allocations are physically -+ * contiguous -+ * @ION_HEAP_TYPE_DMA: memory allocated via DMA API -+ * @ION_HEAP_TYPE_MAX: helper for iterating over standard -+ * (not device specific) heaps -+ * @ION_NUM_HEAPS_IDS: helper for iterating over heaps, a bit mask -+ * is used to identify the heaps, so only 32 -+ * total heap types are supported - */ - enum ion_heap_type { -- ION_HEAP_TYPE_SYSTEM, -- ION_HEAP_TYPE_SYSTEM_CONTIG, -- ION_HEAP_TYPE_CARVEOUT, -- ION_HEAP_TYPE_CHUNK, -- ION_HEAP_TYPE_DMA, -- ION_HEAP_TYPE_CUSTOM, /* -- * must be last so device specific heaps always -- * are at the end of this enum -- */ -+ ION_HEAP_TYPE_SYSTEM = (1 << 0), -+ ION_HEAP_TYPE_SYSTEM_CONTIG = (1 << 1), -+ ION_HEAP_TYPE_CARVEOUT = (1 << 2), -+ ION_HEAP_TYPE_CHUNK = (1 << 3), -+ ION_HEAP_TYPE_DMA = (1 << 4), -+ ION_HEAP_TYPE_MAX = (1 << 15), - }; - - #define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8) -@@ -46,7 +45,7 @@ enum ion_heap_type { - * mappings of this buffer should be cached, ion will do cache maintenance - * when the buffer is mapped for dma - */ --#define ION_FLAG_CACHED 1 -+#define ION_FLAG_CACHED 1 - - /** - * DOC: Ion Userspace API diff --git a/patches/ANDROID-staging-ion-refactor-ion-s-heap-manipulators-into-a-separate-file.patch b/patches/ANDROID-staging-ion-refactor-ion-s-heap-manipulators-into-a-separate-file.patch deleted file mode 100644 index 195ffb58c61515714373d1e79b7bc58382826222..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-refactor-ion-s-heap-manipulators-into-a-separate-file.patch +++ /dev/null @@ -1,398 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Thu, 8 Aug 2019 07:52:27 -0700 -Subject: ANDROID: staging: ion: refactor ion's heap manipulators into a - separate file. - -This patch is preparatory work for making ion heaps modular. The patch -itself doesn't make any significant changes except for re-organizing the -heap manipulator functions in a single file. This will be helpful -later when we specifically export some of these functions to be used by -a heap module. - -Bug: 133508579 -Test: ion-unit-tests - -Change-Id: I19205b4874a3bf52408f1fa14c3e145de1293fb4 -Co-developed-by: Isaac J. Manjarres -Signed-off-by: Sandeep Patil ---- - drivers/staging/android/ion/ion.h | 11 +- - drivers/staging/android/ion/ion_buffer.c | 17 ++ - drivers/staging/android/ion/ion_heap.c | 245 +++++++++--------- - drivers/staging/android/ion/ion_private.h | 1 - - drivers/staging/android/ion/ion_system_heap.c | 2 +- - 5 files changed, 144 insertions(+), 132 deletions(-) - -diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h -index d2d18f03ac77..b5b5412507fd 100644 ---- a/drivers/staging/android/ion/ion.h -+++ b/drivers/staging/android/ion/ion.h -@@ -153,6 +153,14 @@ struct ion_heap { - */ - void ion_device_add_heap(struct ion_heap *heap); - -+/* ion_buffer_zero - zeroes out an ion buffer respecting the ION_FLAGs. -+ * -+ * @buffer: ion_buffer to zero -+ * -+ * Returns 0 on success, negative error otherwise. -+ */ -+int ion_buffer_zero(struct ion_buffer *buffer); -+ - /** - * some helpers for common operations on buffers using the sg_table - * and vaddr fields -@@ -161,8 +169,9 @@ void *ion_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer); - void ion_heap_unmap_kernel(struct ion_heap *heap, struct ion_buffer *buffer); - int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma); --int ion_heap_buffer_zero(struct ion_buffer *buffer); - int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); -+int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, -+ pgprot_t pgprot); - - /** - * ion_heap_init_shrinker -diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c -index c10ea6672f1a..50c2dbc3ebec 100644 ---- a/drivers/staging/android/ion/ion_buffer.c -+++ b/drivers/staging/android/ion/ion_buffer.c -@@ -133,6 +133,23 @@ struct ion_buffer *ion_buffer_alloc(struct ion_device *dev, size_t len, - return buffer; - } - -+int ion_buffer_zero(struct ion_buffer *buffer) -+{ -+ struct sg_table *table; -+ pgprot_t pgprot; -+ -+ if (!buffer) -+ return -EINVAL; -+ -+ table = buffer->sg_table; -+ if (buffer->flags & ION_FLAG_CACHED) -+ pgprot = PAGE_KERNEL; -+ else -+ pgprot = pgprot_writecombine(PAGE_KERNEL); -+ -+ return ion_heap_sglist_zero(table->sgl, table->nents, pgprot); -+} -+ - void ion_buffer_release(struct ion_buffer *buffer) - { - if (buffer->kmap_cnt > 0) { -diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c -index 3b4f32b9cd2d..39eb60e4842e 100644 ---- a/drivers/staging/android/ion/ion_heap.c -+++ b/drivers/staging/android/ion/ion_heap.c -@@ -17,6 +17,120 @@ - - #include "ion_private.h" - -+static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, -+ struct shrink_control *sc) -+{ -+ struct ion_heap *heap = container_of(shrinker, struct ion_heap, -+ shrinker); -+ int total = 0; -+ -+ total = ion_heap_freelist_size(heap) / PAGE_SIZE; -+ -+ if (heap->ops->shrink) -+ total += heap->ops->shrink(heap, sc->gfp_mask, 0); -+ -+ return total; -+} -+ -+static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, -+ struct shrink_control *sc) -+{ -+ struct ion_heap *heap = container_of(shrinker, struct ion_heap, -+ shrinker); -+ int freed = 0; -+ int to_scan = sc->nr_to_scan; -+ -+ if (to_scan == 0) -+ return 0; -+ -+ /* -+ * shrink the free list first, no point in zeroing the memory if we're -+ * just going to reclaim it. Also, skip any possible page pooling. -+ */ -+ if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) -+ freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) / -+ PAGE_SIZE; -+ -+ to_scan -= freed; -+ if (to_scan <= 0) -+ return freed; -+ -+ if (heap->ops->shrink) -+ freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan); -+ -+ return freed; -+} -+ -+static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) -+{ -+ void *addr = vm_map_ram(pages, num, -1, pgprot); -+ -+ if (!addr) -+ return -ENOMEM; -+ memset(addr, 0, PAGE_SIZE * num); -+ vm_unmap_ram(addr, num); -+ -+ return 0; -+} -+ -+static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, -+ bool skip_pools) -+{ -+ struct ion_buffer *buffer; -+ size_t total_drained = 0; -+ -+ if (ion_heap_freelist_size(heap) == 0) -+ return 0; -+ -+ spin_lock(&heap->free_lock); -+ if (size == 0) -+ size = heap->free_list_size; -+ -+ while (!list_empty(&heap->free_list)) { -+ if (total_drained >= size) -+ break; -+ buffer = list_first_entry(&heap->free_list, struct ion_buffer, -+ list); -+ list_del(&buffer->list); -+ heap->free_list_size -= buffer->size; -+ if (skip_pools) -+ buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; -+ total_drained += buffer->size; -+ spin_unlock(&heap->free_lock); -+ ion_buffer_release(buffer); -+ spin_lock(&heap->free_lock); -+ } -+ spin_unlock(&heap->free_lock); -+ -+ return total_drained; -+} -+ -+static int ion_heap_deferred_free(void *data) -+{ -+ struct ion_heap *heap = data; -+ -+ while (true) { -+ struct ion_buffer *buffer; -+ -+ wait_event_freezable(heap->waitqueue, -+ ion_heap_freelist_size(heap) > 0); -+ -+ spin_lock(&heap->free_lock); -+ if (list_empty(&heap->free_list)) { -+ spin_unlock(&heap->free_lock); -+ continue; -+ } -+ buffer = list_first_entry(&heap->free_list, struct ion_buffer, -+ list); -+ list_del(&buffer->list); -+ heap->free_list_size -= buffer->size; -+ spin_unlock(&heap->free_lock); -+ ion_buffer_release(buffer); -+ } -+ -+ return 0; -+} -+ - void *ion_heap_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) - { -@@ -97,20 +211,8 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - return 0; - } - --static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) --{ -- void *addr = vm_map_ram(pages, num, -1, pgprot); -- -- if (!addr) -- return -ENOMEM; -- memset(addr, 0, PAGE_SIZE * num); -- vm_unmap_ram(addr, num); -- -- return 0; --} -- --static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, -- pgprot_t pgprot) -+int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, -+ pgprot_t pgprot) - { - int p = 0; - int ret = 0; -@@ -132,19 +234,6 @@ static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, - return ret; - } - --int ion_heap_buffer_zero(struct ion_buffer *buffer) --{ -- struct sg_table *table = buffer->sg_table; -- pgprot_t pgprot; -- -- if (buffer->flags & ION_FLAG_CACHED) -- pgprot = PAGE_KERNEL; -- else -- pgprot = pgprot_writecombine(PAGE_KERNEL); -- -- return ion_heap_sglist_zero(table->sgl, table->nents, pgprot); --} -- - int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) - { - struct scatterlist sg; -@@ -174,38 +263,6 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) - return size; - } - --static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, -- bool skip_pools) --{ -- struct ion_buffer *buffer; -- size_t total_drained = 0; -- -- if (ion_heap_freelist_size(heap) == 0) -- return 0; -- -- spin_lock(&heap->free_lock); -- if (size == 0) -- size = heap->free_list_size; -- -- while (!list_empty(&heap->free_list)) { -- if (total_drained >= size) -- break; -- buffer = list_first_entry(&heap->free_list, struct ion_buffer, -- list); -- list_del(&buffer->list); -- heap->free_list_size -= buffer->size; -- if (skip_pools) -- buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; -- total_drained += buffer->size; -- spin_unlock(&heap->free_lock); -- ion_buffer_release(buffer); -- spin_lock(&heap->free_lock); -- } -- spin_unlock(&heap->free_lock); -- -- return total_drained; --} -- - size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) - { - return _ion_heap_freelist_drain(heap, size, false); -@@ -216,32 +273,6 @@ size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size) - return _ion_heap_freelist_drain(heap, size, true); - } - --static int ion_heap_deferred_free(void *data) --{ -- struct ion_heap *heap = data; -- -- while (true) { -- struct ion_buffer *buffer; -- -- wait_event_freezable(heap->waitqueue, -- ion_heap_freelist_size(heap) > 0); -- -- spin_lock(&heap->free_lock); -- if (list_empty(&heap->free_list)) { -- spin_unlock(&heap->free_lock); -- continue; -- } -- buffer = list_first_entry(&heap->free_list, struct ion_buffer, -- list); -- list_del(&buffer->list); -- heap->free_list_size -= buffer->size; -- spin_unlock(&heap->free_lock); -- ion_buffer_release(buffer); -- } -- -- return 0; --} -- - int ion_heap_init_deferred_free(struct ion_heap *heap) - { - struct sched_param param = { .sched_priority = 0 }; -@@ -260,50 +291,6 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) - return 0; - } - --static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, -- struct shrink_control *sc) --{ -- struct ion_heap *heap = container_of(shrinker, struct ion_heap, -- shrinker); -- int total = 0; -- -- total = ion_heap_freelist_size(heap) / PAGE_SIZE; -- -- if (heap->ops->shrink) -- total += heap->ops->shrink(heap, sc->gfp_mask, 0); -- -- return total; --} -- --static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, -- struct shrink_control *sc) --{ -- struct ion_heap *heap = container_of(shrinker, struct ion_heap, -- shrinker); -- int freed = 0; -- int to_scan = sc->nr_to_scan; -- -- if (to_scan == 0) -- return 0; -- -- /* -- * shrink the free list first, no point in zeroing the memory if we're -- * just going to reclaim it. Also, skip any possible page pooling. -- */ -- if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) -- freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) / -- PAGE_SIZE; -- -- to_scan -= freed; -- if (to_scan <= 0) -- return freed; -- -- if (heap->ops->shrink) -- freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan); -- -- return freed; --} -- - int ion_heap_init_shrinker(struct ion_heap *heap) - { - heap->shrinker.count_objects = ion_heap_shrink_count; -diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h -index b3c8b55788db..9c8f482cd9d2 100644 ---- a/drivers/staging/android/ion/ion_private.h -+++ b/drivers/staging/android/ion/ion_private.h -@@ -52,5 +52,4 @@ extern struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, - unsigned int flags); - extern int ion_free(struct ion_buffer *buffer); - -- - #endif /* _ION_PRIVATE_H */ -diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c -index ee301df7b7b7..d1cb9e69399e 100644 ---- a/drivers/staging/android/ion/ion_system_heap.c -+++ b/drivers/staging/android/ion/ion_system_heap.c -@@ -161,7 +161,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer) - - /* zero the buffer before goto page pool */ - if (!(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) -- ion_heap_buffer_zero(buffer); -+ ion_buffer_zero(buffer); - - for_each_sg(table->sgl, sg, table->nents, i) - free_buffer_page(sys_heap, buffer, sg_page(sg)); diff --git a/patches/ANDROID-staging-ion-reserve-specific-heap-ids-for-known-heap-types.patch b/patches/ANDROID-staging-ion-reserve-specific-heap-ids-for-known-heap-types.patch deleted file mode 100644 index e78cb8417250a5e5924269e8fbebcf0b0dd79f7c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-reserve-specific-heap-ids-for-known-heap-types.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Mon, 26 Aug 2019 13:14:43 -0700 -Subject: ANDROID: staging: ion: reserve specific heap ids for known heap - types. - -Since its inception, ion used heap types and heap ids interchangeably. -The 'heap type' is not part of the UAPI but 'heap ids' are. The sad part -is that heap ids are dynamically generated and heap types aren't. This -causes all sorts of problems trying to support following things - 1. No UAPI breakage for ION in GKI - 2. Support multiple CMA heaps (i.e. heap with same type but - different ids) - 3. Allow Android system code to reliably talk to any ION - driver using the standard / reserved heap types. etc. - 4. Allow someone to override standard heap implementation. - 5. Allow for new heap types to register to ion core. - -With this change, we start the process of reserving heap ids for -long known heap types like system, carveout etc. In order to not -break ABI and UAPI, we continue to use 32-bits with following caveats - - 1. BIT(0)-BIT(15) are reserved for standard / GKI heap ids - that Android platform can use from now on reliably. - 2. BIT(16)-BIT(31) are reserved for custom heap types that - only vendor specific processes can rely upon. - 3. BIT(3)-BIT(7) are reserved for CARVEOUT heaps. - 4. BIT(8)-BIT(15) are reserved for CMA / DMA heaps that manage - different CMA regions. The heap ids will be allocated in ascending - order and are first come first served. - -Bug: 133508579 -Test:ion-unit-tests - -Change-Id: I53af694113b62d29e0d2933fbcf7079d845099e9 -Signed-off-by: Sandeep Patil ---- - include/uapi/linux/ion.h | 74 +++++++++++++++++++++++++++++----------- - 1 file changed, 55 insertions(+), 19 deletions(-) - -diff --git a/include/uapi/linux/ion.h b/include/uapi/linux/ion.h -index bfcbc0e70921..09dbbfaf3718 100644 ---- a/include/uapi/linux/ion.h -+++ b/include/uapi/linux/ion.h -@@ -12,29 +12,65 @@ - #include - - /** -- * enum ion_heap_types - list of all possible types of heaps -- * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc -- * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc -- * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved -- * carveout heap, allocations are physically -- * contiguous -- * @ION_HEAP_TYPE_DMA: memory allocated via DMA API -- * @ION_HEAP_TYPE_MAX: helper for iterating over standard -- * (not device specific) heaps -- * @ION_NUM_HEAPS_IDS: helper for iterating over heaps, a bit mask -- * is used to identify the heaps, so only 32 -- * total heap types are supported -+ * ion_heap_types - list of all possible types of heaps that Android can use -+ * -+ * @ION_HEAP_TYPE_SYSTEM: Reserved heap id for ion heap that allocates -+ * memory using alloc_page(). Also, supports -+ * deferred free and allocation pools. -+ * @ION_HEAP_TYPE_SYSTEM_CONTIG: Reserved heap id for ion heap that is the same -+ * as SYSTEM_HEAP, except doesn't support -+ * allocation pools. -+ * @ION_HEAP_TYPE_CARVEOUT: Reserved heap id for ion heap that allocates -+ * memory from a pre-reserved memory region -+ * aka 'carveout'. -+ * @ION_HEAP_TYPE_DMA: Reserved heap id for ion heap that manages -+ * single CMA (contiguous memory allocator) -+ * region. Uses standard DMA APIs for -+ * managing memory within the CMA region. - */ - enum ion_heap_type { -- ION_HEAP_TYPE_SYSTEM = (1 << 0), -- ION_HEAP_TYPE_SYSTEM_CONTIG = (1 << 1), -- ION_HEAP_TYPE_CARVEOUT = (1 << 2), -- ION_HEAP_TYPE_CHUNK = (1 << 3), -- ION_HEAP_TYPE_DMA = (1 << 4), -- ION_HEAP_TYPE_MAX = (1 << 15), -+ ION_HEAP_TYPE_SYSTEM = 0, -+ ION_HEAP_TYPE_SYSTEM_CONTIG = 1, -+ ION_HEAP_TYPE_CHUNK = 2, -+ ION_HEAP_TYPE_CARVEOUT = 3, -+ ION_HEAP_TYPE_DMA = 4, -+ /* reserved range for future standard heap types */ -+ ION_HEAP_TYPE_CUSTOM = 16, -+ ION_HEAP_TYPE_MAX = 31, -+}; -+ -+/** -+ * ion_heap_id - list of standard heap ids that Android can use -+ * -+ * @ION_HEAP_SYSTEM Id for the ION_HEAP_TYPE_SYSTEM -+ * @ION_HEAP_SYSTEM_CONTIG Id for the ION_HEAP_TYPE_SYSTEM_CONTIG -+ * @ION_HEAP_CHUNK Id for the ION_HEAP_TYPE_CHUNK -+ * @ION_HEAP_CARVEOUT_START Start of reserved id range for heaps of type -+ * ION_HEAP_TYPE_CARVEOUT -+ * @ION_HEAP_CARVEOUT_END End of reserved id range for heaps of type -+ * ION_HEAP_TYPE_CARVEOUT -+ * @ION_HEAP_DMA_START Start of reserved id range for heaps of type -+ * ION_HEAP_TYPE_DMA -+ * @ION_HEAP_DMA_END End of reserved id range for heaps of type -+ * ION_HEAP_TYPE_DMA -+ * @ION_HEAP_CUSTOM_START Start of reserved id range for heaps of custom -+ * type -+ * @ION_HEAP_CUSTOM_END End of reserved id range for heaps of custom -+ * type -+ */ -+enum ion_heap_id { -+ ION_HEAP_SYSTEM = (1 << ION_HEAP_TYPE_SYSTEM), -+ ION_HEAP_SYSTEM_CONTIG = (ION_HEAP_SYSTEM << 1), -+ ION_HEAP_CHUNK = (ION_HEAP_SYSTEM_CONTIG << 1), -+ ION_HEAP_CARVEOUT_START = (ION_HEAP_CHUNK << 1), -+ ION_HEAP_CARVEOUT_END = (ION_HEAP_CARVEOUT_START << 4), -+ ION_HEAP_DMA_START = (ION_HEAP_CARVEOUT_END << 1), -+ ION_HEAP_DMA_END = (ION_HEAP_DMA_START << 7), -+ ION_HEAP_CUSTOM_START = (ION_HEAP_DMA_END << 1), -+ ION_HEAP_CUSTOM_END = (ION_HEAP_CUSTOM_START << 15), - }; - --#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8) -+#define ION_NUM_MAX_HEAPS (32) - - /** - * allocation flags - the lower 16 bits are used by core ion, the upper 16 diff --git a/patches/ANDROID-staging-ion-split-system-and-system-contig-heaps.patch b/patches/ANDROID-staging-ion-split-system-and-system-contig-heaps.patch deleted file mode 100644 index cc52e3510e3548cd6fb1dea4cfc949c0ec28a560..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-split-system-and-system-contig-heaps.patch +++ /dev/null @@ -1,297 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Thu, 8 Aug 2019 08:50:56 -0700 -Subject: ANDROID: staging: ion: split system and system-contig heaps - -This will allows us to build and load them both as individual -kernel modules. - -Bug: 133508579 -Test: ion-unit-tests - -Change-Id: I8bdada5531fbf148e4d097e94e406a232874913a -Signed-off-by: Sandeep Patil ---- - arch/arm64/configs/gki_defconfig | 2 + - arch/x86/configs/gki_defconfig | 2 + - drivers/staging/android/ion/heaps/Kconfig | 8 ++ - drivers/staging/android/ion/heaps/Makefile | 1 + - .../ion/heaps/ion_system_contig_heap.c | 111 ++++++++++++++++++ - .../android/ion/heaps/ion_system_heap.c | 95 --------------- - 6 files changed, 124 insertions(+), 95 deletions(-) - create mode 100644 drivers/staging/android/ion/heaps/ion_system_contig_heap.c - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 539f42574383..73acbe383203 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -349,6 +349,8 @@ CONFIG_STAGING=y - CONFIG_ASHMEM=y - CONFIG_ANDROID_VSOC=y - CONFIG_ION=y -+CONFIG_ION_SYSTEM_HEAP=y -+CONFIG_ION_SYSTEM_CONTIG_HEAP=y - CONFIG_COMMON_CLK_SCPI=y - CONFIG_HWSPINLOCK=y - CONFIG_MAILBOX=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 2d5f55d7b966..ae3d165a79c3 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -289,6 +289,8 @@ CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y - CONFIG_STAGING=y - CONFIG_ASHMEM=y - CONFIG_ION=y -+CONFIG_ION_SYSTEM_HEAP=y -+CONFIG_ION_SYSTEM_CONTIG_HEAP=y - CONFIG_PM_DEVFREQ=y - CONFIG_ANDROID=y - CONFIG_ANDROID_BINDER_IPC=y -diff --git a/drivers/staging/android/ion/heaps/Kconfig b/drivers/staging/android/ion/heaps/Kconfig -index 7affa91ecabb..f1c7a6b79c01 100644 ---- a/drivers/staging/android/ion/heaps/Kconfig -+++ b/drivers/staging/android/ion/heaps/Kconfig -@@ -6,6 +6,14 @@ config ION_SYSTEM_HEAP - Choose this option to enable the Ion system heap. The system heap - is backed by pages from the buddy allocator. If in doubt, say Y. - -+config ION_SYSTEM_CONTIG_HEAP -+ bool "Ion system contig heap" -+ depends on ION -+ help -+ Choose this option to enable Ion system contig heap. The system contig heap -+ is backed by the pages from buddy allocator that are guaranteed to be physically -+ contiguous. If in doubt, say Y. -+ - config ION_CMA_HEAP - bool "Ion CMA heap support" - depends on ION && DMA_CMA -diff --git a/drivers/staging/android/ion/heaps/Makefile b/drivers/staging/android/ion/heaps/Makefile -index 127912629f0b..e2ee931100d0 100644 ---- a/drivers/staging/android/ion/heaps/Makefile -+++ b/drivers/staging/android/ion/heaps/Makefile -@@ -1,3 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0 - obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o -+obj-$(CONFIG_ION_SYSTEM_CONTIG_HEAP) += ion_system_contig_heap.o - obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o -diff --git a/drivers/staging/android/ion/heaps/ion_system_contig_heap.c b/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -new file mode 100644 -index 000000000000..3a07ef931c2e ---- /dev/null -+++ b/drivers/staging/android/ion/heaps/ion_system_contig_heap.c -@@ -0,0 +1,111 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * ION Memory Allocator system contig heap exporter -+ * -+ * Copyright (C) 2019 Google, Inc. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int ion_system_contig_heap_allocate(struct ion_heap *heap, -+ struct ion_buffer *buffer, -+ unsigned long len, -+ unsigned long flags) -+{ -+ int order = get_order(len); -+ struct page *page; -+ struct sg_table *table; -+ unsigned long i; -+ int ret; -+ -+ page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN, order); -+ if (!page) -+ return -ENOMEM; -+ -+ split_page(page, order); -+ -+ len = PAGE_ALIGN(len); -+ for (i = len >> PAGE_SHIFT; i < (1 << order); i++) -+ __free_page(page + i); -+ -+ table = kmalloc(sizeof(*table), GFP_KERNEL); -+ if (!table) { -+ ret = -ENOMEM; -+ goto free_pages; -+ } -+ -+ ret = sg_alloc_table(table, 1, GFP_KERNEL); -+ if (ret) -+ goto free_table; -+ -+ sg_set_page(table->sgl, page, len, 0); -+ -+ buffer->sg_table = table; -+ -+ return 0; -+ -+free_table: -+ kfree(table); -+free_pages: -+ for (i = 0; i < len >> PAGE_SHIFT; i++) -+ __free_page(page + i); -+ -+ return ret; -+} -+ -+static void ion_system_contig_heap_free(struct ion_buffer *buffer) -+{ -+ struct sg_table *table = buffer->sg_table; -+ struct page *page = sg_page(table->sgl); -+ unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT; -+ unsigned long i; -+ -+ for (i = 0; i < pages; i++) -+ __free_page(page + i); -+ sg_free_table(table); -+ kfree(table); -+} -+ -+static struct ion_heap_ops kmalloc_ops = { -+ .allocate = ion_system_contig_heap_allocate, -+ .free = ion_system_contig_heap_free, -+ .map_kernel = ion_heap_map_kernel, -+ .unmap_kernel = ion_heap_unmap_kernel, -+ .map_user = ion_heap_map_user, -+}; -+ -+static struct ion_heap *__ion_system_contig_heap_create(void) -+{ -+ struct ion_heap *heap; -+ -+ heap = kzalloc(sizeof(*heap), GFP_KERNEL); -+ if (!heap) -+ return ERR_PTR(-ENOMEM); -+ heap->ops = &kmalloc_ops; -+ heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; -+ heap->name = "ion_system_contig_heap"; -+ -+ return heap; -+} -+ -+static int ion_system_contig_heap_create(void) -+{ -+ struct ion_heap *heap; -+ -+ heap = __ion_system_contig_heap_create(); -+ if (IS_ERR(heap)) -+ return PTR_ERR(heap); -+ -+ ion_device_add_heap(heap); -+ -+ return 0; -+} -+device_initcall(ion_system_contig_heap_create); -+ -diff --git a/drivers/staging/android/ion/heaps/ion_system_heap.c b/drivers/staging/android/ion/heaps/ion_system_heap.c -index afb2a6385705..25ea31757578 100644 ---- a/drivers/staging/android/ion/heaps/ion_system_heap.c -+++ b/drivers/staging/android/ion/heaps/ion_system_heap.c -@@ -281,98 +281,3 @@ static int ion_system_heap_create(void) - return 0; - } - device_initcall(ion_system_heap_create); -- --static int ion_system_contig_heap_allocate(struct ion_heap *heap, -- struct ion_buffer *buffer, -- unsigned long len, -- unsigned long flags) --{ -- int order = get_order(len); -- struct page *page; -- struct sg_table *table; -- unsigned long i; -- int ret; -- -- page = alloc_pages(low_order_gfp_flags | __GFP_NOWARN, order); -- if (!page) -- return -ENOMEM; -- -- split_page(page, order); -- -- len = PAGE_ALIGN(len); -- for (i = len >> PAGE_SHIFT; i < (1 << order); i++) -- __free_page(page + i); -- -- table = kmalloc(sizeof(*table), GFP_KERNEL); -- if (!table) { -- ret = -ENOMEM; -- goto free_pages; -- } -- -- ret = sg_alloc_table(table, 1, GFP_KERNEL); -- if (ret) -- goto free_table; -- -- sg_set_page(table->sgl, page, len, 0); -- -- buffer->sg_table = table; -- -- return 0; -- --free_table: -- kfree(table); --free_pages: -- for (i = 0; i < len >> PAGE_SHIFT; i++) -- __free_page(page + i); -- -- return ret; --} -- --static void ion_system_contig_heap_free(struct ion_buffer *buffer) --{ -- struct sg_table *table = buffer->sg_table; -- struct page *page = sg_page(table->sgl); -- unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT; -- unsigned long i; -- -- for (i = 0; i < pages; i++) -- __free_page(page + i); -- sg_free_table(table); -- kfree(table); --} -- --static struct ion_heap_ops kmalloc_ops = { -- .allocate = ion_system_contig_heap_allocate, -- .free = ion_system_contig_heap_free, -- .map_kernel = ion_heap_map_kernel, -- .unmap_kernel = ion_heap_unmap_kernel, -- .map_user = ion_heap_map_user, --}; -- --static struct ion_heap *__ion_system_contig_heap_create(void) --{ -- struct ion_heap *heap; -- -- heap = kzalloc(sizeof(*heap), GFP_KERNEL); -- if (!heap) -- return ERR_PTR(-ENOMEM); -- heap->ops = &kmalloc_ops; -- heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; -- heap->name = "ion_system_contig_heap"; -- -- return heap; --} -- --static int ion_system_contig_heap_create(void) --{ -- struct ion_heap *heap; -- -- heap = __ion_system_contig_heap_create(); -- if (IS_ERR(heap)) -- return PTR_ERR(heap); -- -- ion_device_add_heap(heap); -- -- return 0; --} --device_initcall(ion_system_contig_heap_create); diff --git a/patches/ANDROID-staging-ion-uapi-match-the-existing-heap-type-enums.patch b/patches/ANDROID-staging-ion-uapi-match-the-existing-heap-type-enums.patch deleted file mode 100644 index 20602bd7e25873a51bb4b6a9b66519386a50ebd3..0000000000000000000000000000000000000000 --- a/patches/ANDROID-staging-ion-uapi-match-the-existing-heap-type-enums.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sandeep Patil -Date: Mon, 9 Sep 2019 08:34:43 -0700 -Subject: ANDROID: staging: ion: uapi: match the existing heap type enums - -Change the enup order for ion heap types to match how it was before so -as to not break any userspace code that depends on them. - -Bug: 140507100 -Test: ion-unit-tests - -Change-Id: Id68c50a9bd3eda2ce46bc88a326a120c52d1110f -Signed-off-by: Sandeep Patil ---- - include/uapi/linux/ion.h | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/include/uapi/linux/ion.h b/include/uapi/linux/ion.h -index 09dbbfaf3718..ad773e5fa4d2 100644 ---- a/include/uapi/linux/ion.h -+++ b/include/uapi/linux/ion.h -@@ -31,8 +31,8 @@ - enum ion_heap_type { - ION_HEAP_TYPE_SYSTEM = 0, - ION_HEAP_TYPE_SYSTEM_CONTIG = 1, -- ION_HEAP_TYPE_CHUNK = 2, -- ION_HEAP_TYPE_CARVEOUT = 3, -+ ION_HEAP_TYPE_CARVEOUT = 2, -+ ION_HEAP_TYPE_CHUNK = 3, - ION_HEAP_TYPE_DMA = 4, - /* reserved range for future standard heap types */ - ION_HEAP_TYPE_CUSTOM = 16, -@@ -61,10 +61,10 @@ enum ion_heap_type { - enum ion_heap_id { - ION_HEAP_SYSTEM = (1 << ION_HEAP_TYPE_SYSTEM), - ION_HEAP_SYSTEM_CONTIG = (ION_HEAP_SYSTEM << 1), -- ION_HEAP_CHUNK = (ION_HEAP_SYSTEM_CONTIG << 1), -- ION_HEAP_CARVEOUT_START = (ION_HEAP_CHUNK << 1), -+ ION_HEAP_CARVEOUT_START = (ION_HEAP_SYSTEM_CONTIG << 1), - ION_HEAP_CARVEOUT_END = (ION_HEAP_CARVEOUT_START << 4), -- ION_HEAP_DMA_START = (ION_HEAP_CARVEOUT_END << 1), -+ ION_HEAP_CHUNK = (ION_HEAP_CARVEOUT_END << 1), -+ ION_HEAP_DMA_START = (ION_HEAP_CHUNK << 1), - ION_HEAP_DMA_END = (ION_HEAP_DMA_START << 7), - ION_HEAP_CUSTOM_START = (ION_HEAP_DMA_END << 1), - ION_HEAP_CUSTOM_END = (ION_HEAP_CUSTOM_START << 15), diff --git a/patches/ANDROID-sync-defconfigs-with-savedefconfig.patch b/patches/ANDROID-sync-defconfigs-with-savedefconfig.patch deleted file mode 100644 index f0f92c8ab6a3d15e3ad129bf69a95e5c20c5d096..0000000000000000000000000000000000000000 --- a/patches/ANDROID-sync-defconfigs-with-savedefconfig.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Mon, 20 May 2019 11:54:22 -0700 -Subject: ANDROID: sync defconfigs with savedefconfig - -Test: boot gki_defconfig and cuttlefish_defconfig on arm64 cuttlefish -Signed-off-by: Tri Vo -Change-Id: Ie0b518c0fd5100a39312069fe3b193684feb634d ---- - arch/arm64/configs/gki_defconfig | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 04f531ef2511..c9720858fd9a 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -35,13 +35,13 @@ CONFIG_PROFILING=y - CONFIG_SCHED_MC=y - CONFIG_SECCOMP=y - CONFIG_PARAVIRT=y -+CONFIG_COMPAT=y - CONFIG_ARMV8_DEPRECATED=y - CONFIG_SWP_EMULATION=y - CONFIG_CP15_BARRIER_EMULATION=y - CONFIG_SETEND_EMULATION=y - CONFIG_RANDOMIZE_BASE=y - # CONFIG_EFI is not set --CONFIG_COMPAT=y - CONFIG_PM_WAKELOCKS=y - CONFIG_PM_WAKELOCKS_LIMIT=0 - # CONFIG_PM_WAKELOCKS_GC is not set -@@ -81,7 +81,6 @@ CONFIG_IP_MULTIPLE_TABLES=y - CONFIG_NET_IPGRE_DEMUX=y - CONFIG_NET_IPVTI=y - CONFIG_INET_ESP=y --# CONFIG_INET_XFRM_MODE_BEET is not set - CONFIG_INET_UDP_DIAG=y - CONFIG_INET_DIAG_DESTROY=y - CONFIG_IPV6_ROUTER_PREF=y -@@ -180,7 +179,6 @@ CONFIG_MAC80211=y - CONFIG_RFKILL=y - CONFIG_PCI=y - CONFIG_PCI_HOST_GENERIC=y --# CONFIG_UEVENT_HELPER is not set - # CONFIG_ALLOW_DEV_COREDUMP is not set - CONFIG_DEBUG_DEVRES=y - CONFIG_ZRAM=y -@@ -282,7 +280,6 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set - CONFIG_DRM_VIRTIO_GPU=y --CONFIG_BACKLIGHT_LCD_SUPPORT=y - # CONFIG_LCD_CLASS_DEVICE is not set - CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_SOUND=y diff --git a/patches/ANDROID-taskstats-track-fsync-syscalls.patch b/patches/ANDROID-taskstats-track-fsync-syscalls.patch deleted file mode 100644 index a3d423616b0a6c3a132ca1d7c56e1c5f201993cd..0000000000000000000000000000000000000000 --- a/patches/ANDROID-taskstats-track-fsync-syscalls.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jin Qian -Date: Thu, 2 Mar 2017 13:32:59 -0800 -Subject: ANDROID: taskstats: track fsync syscalls - -This adds a counter to the taskstats extended accounting fields, which -tracks the number of times fsync is called, and then plumbs it through -to the uid_sys_stats driver. - -Bug: 120442023 -Change-Id: I6c138de5b2332eea70f57e098134d1d141247b3f -Signed-off-by: Jin Qian -[AmitP: Refactored changes to align with changes from upstream commit - 9a07000400c8 ("sched/headers: Move CONFIG_TASK_XACCT bits from to ")] -Signed-off-by: Amit Pundir -[tkjos: Needed for storaged fsync accounting ("storaged --uid" and - "storaged --task").] -[astrachan: This is modifying a userspace interface and should probably - be reworked] -Signed-off-by: Alistair Strachan ---- - drivers/misc/Kconfig | 2 +- - drivers/misc/uid_sys_stats.c | 2 ++ - fs/sync.c | 3 ++- - include/linux/sched/xacct.h | 9 +++++++++ - include/linux/task_io_accounting.h | 2 ++ - include/linux/task_io_accounting_ops.h | 1 + - 6 files changed, 17 insertions(+), 2 deletions(-) - -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index a067f988d0f4..ca90dacfb016 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -460,7 +460,7 @@ config MISC_RTSX - - config UID_SYS_STATS - bool "Per-UID statistics" -- depends on PROFILING && TASK_IO_ACCOUNTING -+ depends on PROFILING && TASK_XACCT && TASK_IO_ACCOUNTING - help - Per UID based cpu time statistics exported to /proc/uid_cputime - Per UID based io statistics exported to /proc/uid_io -diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c -index ea23f5d0af43..36b5f37fca2f 100644 ---- a/drivers/misc/uid_sys_stats.c -+++ b/drivers/misc/uid_sys_stats.c -@@ -249,6 +249,7 @@ static void add_uid_tasks_io_stats(struct uid_entry *uid_entry, - task_io_slot->write_bytes += compute_write_bytes(task); - task_io_slot->rchar += task->ioac.rchar; - task_io_slot->wchar += task->ioac.wchar; -+ task_io_slot->fsync += task->ioac.syscfs; - } - - static void compute_io_uid_tasks(struct uid_entry *uid_entry) -@@ -452,6 +453,7 @@ static void add_uid_io_stats(struct uid_entry *uid_entry, - io_slot->write_bytes += compute_write_bytes(task); - io_slot->rchar += task->ioac.rchar; - io_slot->wchar += task->ioac.wchar; -+ io_slot->fsync += task->ioac.syscfs; - - add_uid_tasks_io_stats(uid_entry, task, slot); - } -diff --git a/fs/sync.c b/fs/sync.c -index 4d1ff010bc5a..cc475d8be0c1 100644 ---- a/fs/sync.c -+++ b/fs/sync.c -@@ -9,7 +9,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -220,6 +220,7 @@ static int do_fsync(unsigned int fd, int datasync) - if (f.file) { - ret = vfs_fsync(f.file, datasync); - fdput(f); -+ inc_syscfs(current); - } - return ret; - } -diff --git a/include/linux/sched/xacct.h b/include/linux/sched/xacct.h -index c078f0a94cec..9544c9d9d534 100644 ---- a/include/linux/sched/xacct.h -+++ b/include/linux/sched/xacct.h -@@ -28,6 +28,11 @@ static inline void inc_syscw(struct task_struct *tsk) - { - tsk->ioac.syscw++; - } -+ -+static inline void inc_syscfs(struct task_struct *tsk) -+{ -+ tsk->ioac.syscfs++; -+} - #else - static inline void add_rchar(struct task_struct *tsk, ssize_t amt) - { -@@ -44,6 +49,10 @@ static inline void inc_syscr(struct task_struct *tsk) - static inline void inc_syscw(struct task_struct *tsk) - { - } -+ -+static inline void inc_syscfs(struct task_struct *tsk) -+{ -+} - #endif - - #endif /* _LINUX_SCHED_XACCT_H */ -diff --git a/include/linux/task_io_accounting.h b/include/linux/task_io_accounting.h -index 6f6acce064de..bb26108ca23c 100644 ---- a/include/linux/task_io_accounting.h -+++ b/include/linux/task_io_accounting.h -@@ -19,6 +19,8 @@ struct task_io_accounting { - u64 syscr; - /* # of write syscalls */ - u64 syscw; -+ /* # of fsync syscalls */ -+ u64 syscfs; - #endif /* CONFIG_TASK_XACCT */ - - #ifdef CONFIG_TASK_IO_ACCOUNTING -diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h -index bb5498bcdd96..733ab62ae141 100644 ---- a/include/linux/task_io_accounting_ops.h -+++ b/include/linux/task_io_accounting_ops.h -@@ -97,6 +97,7 @@ static inline void task_chr_io_accounting_add(struct task_io_accounting *dst, - dst->wchar += src->wchar; - dst->syscr += src->syscr; - dst->syscw += src->syscw; -+ dst->syscfs += src->syscfs; - } - #else - static inline void task_chr_io_accounting_add(struct task_io_accounting *dst, diff --git a/patches/ANDROID-uid_cputime-Adds-accounting-for-the-cputimes-per-uid.patch b/patches/ANDROID-uid_cputime-Adds-accounting-for-the-cputimes-per-uid.patch deleted file mode 100644 index a0dea29a5ecbf622a4731d42445a4b14070d94c6..0000000000000000000000000000000000000000 --- a/patches/ANDROID-uid_cputime-Adds-accounting-for-the-cputimes-per-uid.patch +++ /dev/null @@ -1,314 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jin Qian -Date: Wed, 11 Mar 2015 10:44:50 -0700 -Subject: ANDROID: uid_cputime: Adds accounting for the cputimes per uid. - -Adds proc files /proc/uid_cputime/show_uid_stat and -/proc/uid_cputime/remove_uid_range. - -show_uid_stat lists the total utime and stime for the active as well as -terminated processes for each of the uids. - -Writing a range of uids to remove_uid_range will delete the accounting -for all the uids within that range. - -Bug: 120442023 -Change-Id: I21d9210379da730b33ddc1a0ea663c8c9d2ac15b -Signed-off-by: Jin Qian -[AmitP: Refactored the original patch because upstream commit - 605dc2b31a2a ("tsacct: Convert obsolete cputime type to nsecs") - made cputime_t type obsolete, so use u64 nanoseconds directly instead. - Also folded following android-4.9 changes into this patch - 48a9906c0fd8 ("ANDROID: proc: uid_cputime: create uids from kuids") - 453ac31cab34 ("ANDROID: proc: uid_cputime: fix show_uid_stat permission")] -Signed-off-by: Amit Pundir -[connoro: Used by batterystats.] -[astrachan: Folded in the file/kconfig rename and the following changes: - da3687fbc393 ("ANDROID: uid_cputime: fix cputime overflow") - 71e3eb512d00 ("ANDROID: uid_cputime: Iterates over all the threads instead of processes.") - c65f0080c300 ("ANDROID: uid_cputime: Check for the range while removing range of UIDs.") - c8212458e3a5 ("ANDROID: uid_sys_stats: fix access of task_uid(task)") - bb5ee21cc4dd ("ANDROID: uid_sys_stats: change to use rt_mutex") - 6dc5d8173a8c ("ANDROID: uid_sys_stats: check previous uid_entry before call find_or_register_uid") - 82b9872b3894 ("ANDROID: uid_sys_stats: Replace tasklist lock with RCU in uid_cputime_show")] -Signed-off-by: Alistair Strachan ---- - drivers/misc/Kconfig | 6 + - drivers/misc/Makefile | 1 + - drivers/misc/uid_sys_stats.c | 241 +++++++++++++++++++++++++++++++++++ - 3 files changed, 248 insertions(+) - create mode 100644 drivers/misc/uid_sys_stats.c - -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index c55b63750757..ef553e6eb1cd 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -458,6 +458,12 @@ config MISC_RTSX - tristate - default MISC_RTSX_PCI || MISC_RTSX_USB - -+config UID_SYS_STATS -+ bool "Per-UID statistics" -+ depends on PROFILING -+ help -+ Per UID based cpu time statistics exported to /proc/uid_cputime -+ - config PVPANIC - tristate "pvpanic device support" - depends on HAS_IOMEM && (ACPI || OF) -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index c1860d35dc7e..9a3dda3a9d06 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -57,3 +57,4 @@ obj-y += cardreader/ - obj-$(CONFIG_PVPANIC) += pvpanic.o - obj-$(CONFIG_HABANA_AI) += habanalabs/ - obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o -+obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o -diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c -new file mode 100644 -index 000000000000..e1a9ef29468f ---- /dev/null -+++ b/drivers/misc/uid_sys_stats.c -@@ -0,0 +1,241 @@ -+/* drivers/misc/uid_sys_stats.c -+ * -+ * Copyright (C) 2014 - 2015 Google, Inc. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#define UID_HASH_BITS 10 -+DECLARE_HASHTABLE(hash_table, UID_HASH_BITS); -+ -+static DEFINE_RT_MUTEX(uid_lock); -+static struct proc_dir_entry *parent; -+ -+struct uid_entry { -+ uid_t uid; -+ u64 utime; -+ u64 stime; -+ u64 active_utime; -+ u64 active_stime; -+ struct hlist_node hash; -+}; -+ -+static struct uid_entry *find_uid_entry(uid_t uid) -+{ -+ struct uid_entry *uid_entry; -+ hash_for_each_possible(hash_table, uid_entry, hash, uid) { -+ if (uid_entry->uid == uid) -+ return uid_entry; -+ } -+ return NULL; -+} -+ -+static struct uid_entry *find_or_register_uid(uid_t uid) -+{ -+ struct uid_entry *uid_entry; -+ -+ uid_entry = find_uid_entry(uid); -+ if (uid_entry) -+ return uid_entry; -+ -+ uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC); -+ if (!uid_entry) -+ return NULL; -+ -+ uid_entry->uid = uid; -+ -+ hash_add(hash_table, &uid_entry->hash, uid); -+ -+ return uid_entry; -+} -+ -+static int uid_stat_show(struct seq_file *m, void *v) -+{ -+ struct uid_entry *uid_entry = NULL; -+ struct task_struct *task, *temp; -+ struct user_namespace *user_ns = current_user_ns(); -+ u64 utime; -+ u64 stime; -+ unsigned long 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; -+ } -+ -+ rcu_read_lock(); -+ do_each_thread(temp, task) { -+ uid = from_kuid_munged(user_ns, task_uid(task)); -+ 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); -+ pr_err("%s: failed to find the uid_entry for uid %d\n", -+ __func__, uid); -+ return -ENOMEM; -+ } -+ task_cputime_adjusted(task, &utime, &stime); -+ uid_entry->active_utime += utime; -+ uid_entry->active_stime += stime; -+ } 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_ms(total_utime), ktime_to_ms(total_stime)); -+ } -+ -+ rt_mutex_unlock(&uid_lock); -+ return 0; -+} -+ -+static int uid_stat_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, uid_stat_show, PDE_DATA(inode)); -+} -+ -+static const struct file_operations uid_stat_fops = { -+ .open = uid_stat_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static int uid_remove_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, NULL, NULL); -+} -+ -+static ssize_t uid_remove_write(struct file *file, -+ const char __user *buffer, size_t count, loff_t *ppos) -+{ -+ struct uid_entry *uid_entry; -+ struct hlist_node *tmp; -+ char uids[128]; -+ char *start_uid, *end_uid = NULL; -+ long int uid_start = 0, uid_end = 0; -+ -+ if (count >= sizeof(uids)) -+ count = sizeof(uids) - 1; -+ -+ if (copy_from_user(uids, buffer, count)) -+ return -EFAULT; -+ -+ uids[count] = '\0'; -+ end_uid = uids; -+ start_uid = strsep(&end_uid, "-"); -+ -+ if (!start_uid || !end_uid) -+ return -EINVAL; -+ -+ if (kstrtol(start_uid, 10, &uid_start) != 0 || -+ kstrtol(end_uid, 10, &uid_end) != 0) { -+ return -EINVAL; -+ } -+ rt_mutex_lock(&uid_lock); -+ -+ for (; uid_start <= uid_end; uid_start++) { -+ hash_for_each_possible_safe(hash_table, uid_entry, tmp, -+ hash, (uid_t)uid_start) { -+ if (uid_start == uid_entry->uid) { -+ hash_del(&uid_entry->hash); -+ kfree(uid_entry); -+ } -+ } -+ } -+ -+ rt_mutex_unlock(&uid_lock); -+ return count; -+} -+ -+static const struct file_operations uid_remove_fops = { -+ .open = uid_remove_open, -+ .release = single_release, -+ .write = uid_remove_write, -+}; -+ -+static int process_notifier(struct notifier_block *self, -+ unsigned long cmd, void *v) -+{ -+ struct task_struct *task = v; -+ struct uid_entry *uid_entry; -+ u64 utime, stime; -+ uid_t uid; -+ -+ if (!task) -+ return NOTIFY_OK; -+ -+ rt_mutex_lock(&uid_lock); -+ uid = from_kuid_munged(current_user_ns(), task_uid(task)); -+ uid_entry = find_or_register_uid(uid); -+ if (!uid_entry) { -+ pr_err("%s: failed to find uid %d\n", __func__, uid); -+ goto exit; -+ } -+ -+ task_cputime_adjusted(task, &utime, &stime); -+ uid_entry->utime += utime; -+ uid_entry->stime += stime; -+ -+exit: -+ rt_mutex_unlock(&uid_lock); -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block process_notifier_block = { -+ .notifier_call = process_notifier, -+}; -+ -+static int __init proc_uid_cputime_init(void) -+{ -+ hash_init(hash_table); -+ -+ parent = proc_mkdir("uid_cputime", NULL); -+ if (!parent) { -+ pr_err("%s: failed to create proc entry\n", __func__); -+ return -ENOMEM; -+ } -+ -+ proc_create_data("remove_uid_range", S_IWUGO, parent, &uid_remove_fops, -+ NULL); -+ -+ proc_create_data("show_uid_stat", S_IRUGO, parent, &uid_stat_fops, -+ NULL); -+ -+ profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block); -+ -+ return 0; -+} -+ -+early_initcall(proc_uid_cputime_init); diff --git a/patches/ANDROID-uid_cputime-add-per-uid-IO-usage-accounting.patch b/patches/ANDROID-uid_cputime-add-per-uid-IO-usage-accounting.patch deleted file mode 100644 index aaadda4015a4354a7490e52160f2d21f008744d2..0000000000000000000000000000000000000000 --- a/patches/ANDROID-uid_cputime-add-per-uid-IO-usage-accounting.patch +++ /dev/null @@ -1,647 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jin Qian -Date: Tue, 10 Jan 2017 16:10:35 -0800 -Subject: ANDROID: uid_cputime: add per-uid IO usage accounting - -IO usages are accounted in foreground and background buckets. -For each uid, io usage is calculated in two steps. - -delta = current total of all uid tasks - previus total -current bucket += delta - -Bucket is determined by current uid stat. Userspace writes to -/proc/uid_procstat/set when uid stat is updated. - -/proc/uid_io/stats shows IO usage in this format. - - -Bug: 34198239 -Bug: 120442023 -Change-Id: Ib8bebda53e7a56f45ea3eb0ec9a3153d44188102 -Signed-off-by: Jin Qian -[connoro: Used by storaged.] -[astrachan: Note: this version does not track fsync syscalls; this is - implemented in a follow up due to the fact it depends on - modifications to the task_xacct feature.] -[astrachan: Folded in the following changes: - e003a91d8f42 ("ANDROID: uid_sys_stats: allow writing same state") - 89b984bf2efd ("ANDROID: uid_sys_stats: fix negative write bytes.") - bb5ee21cc4dd ("ANDROID: uid_sys_stats: change to use rt_mutex") - 9297d5a160c7 ("ANDROID: uid_sys_stats: reduce update_io_stats overhead") - 89402d07fe91 ("ANDROID: uid_sys_stats: defer io stats calulation for dead tasks") - 6dc5d8173a8c ("ANDROID: uid_sys_stats: check previous uid_entry before call find_or_register_uid") - 0ca2ece8f7ec ("ANDROID: uid_sys_stats: log task io with a debug flag") - c9c096ef0e67 ("ANDROID: uid_sys_stats: Copy task_struct comm field to bigger buffer")] -Signed-off-by: Alistair Strachan ---- - drivers/misc/Kconfig | 11 +- - drivers/misc/uid_sys_stats.c | 490 +++++++++++++++++++++++++++++++++-- - 2 files changed, 483 insertions(+), 18 deletions(-) - -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index ef553e6eb1cd..a067f988d0f4 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -460,9 +460,18 @@ config MISC_RTSX - - config UID_SYS_STATS - bool "Per-UID statistics" -- depends on PROFILING -+ depends on PROFILING && TASK_IO_ACCOUNTING - help - Per UID based cpu time statistics exported to /proc/uid_cputime -+ Per UID based io statistics exported to /proc/uid_io -+ Per UID based procstat control in /proc/uid_procstat -+ -+config UID_SYS_STATS_DEBUG -+ bool "Per-TASK statistics" -+ depends on UID_SYS_STATS -+ default n -+ help -+ Per TASK based io statistics exported to /proc/uid_io - - config PVPANIC - tristate "pvpanic device support" -diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c -index e1a9ef29468f..ea23f5d0af43 100644 ---- a/drivers/misc/uid_sys_stats.c -+++ b/drivers/misc/uid_sys_stats.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -32,7 +33,35 @@ - DECLARE_HASHTABLE(hash_table, UID_HASH_BITS); - - static DEFINE_RT_MUTEX(uid_lock); --static struct proc_dir_entry *parent; -+static struct proc_dir_entry *cpu_parent; -+static struct proc_dir_entry *io_parent; -+static struct proc_dir_entry *proc_parent; -+ -+struct io_stats { -+ u64 read_bytes; -+ u64 write_bytes; -+ u64 rchar; -+ u64 wchar; -+ u64 fsync; -+}; -+ -+#define UID_STATE_FOREGROUND 0 -+#define UID_STATE_BACKGROUND 1 -+#define UID_STATE_BUCKET_SIZE 2 -+ -+#define UID_STATE_TOTAL_CURR 2 -+#define UID_STATE_TOTAL_LAST 3 -+#define UID_STATE_DEAD_TASKS 4 -+#define UID_STATE_SIZE 5 -+ -+#define MAX_TASK_COMM_LEN 256 -+ -+struct task_entry { -+ char comm[MAX_TASK_COMM_LEN]; -+ pid_t pid; -+ struct io_stats io[UID_STATE_SIZE]; -+ struct hlist_node hash; -+}; - - struct uid_entry { - uid_t uid; -@@ -40,9 +69,233 @@ struct uid_entry { - u64 stime; - u64 active_utime; - u64 active_stime; -+ int state; -+ struct io_stats io[UID_STATE_SIZE]; - struct hlist_node hash; -+#ifdef CONFIG_UID_SYS_STATS_DEBUG -+ DECLARE_HASHTABLE(task_entries, UID_HASH_BITS); -+#endif - }; - -+static u64 compute_write_bytes(struct task_struct *task) -+{ -+ if (task->ioac.write_bytes <= task->ioac.cancelled_write_bytes) -+ return 0; -+ -+ return task->ioac.write_bytes - task->ioac.cancelled_write_bytes; -+} -+ -+static void compute_io_bucket_stats(struct io_stats *io_bucket, -+ struct io_stats *io_curr, -+ struct io_stats *io_last, -+ struct io_stats *io_dead) -+{ -+ /* tasks could switch to another uid group, but its io_last in the -+ * previous uid group could still be positive. -+ * therefore before each update, do an overflow check first -+ */ -+ int64_t delta; -+ -+ delta = io_curr->read_bytes + io_dead->read_bytes - -+ io_last->read_bytes; -+ io_bucket->read_bytes += delta > 0 ? delta : 0; -+ delta = io_curr->write_bytes + io_dead->write_bytes - -+ io_last->write_bytes; -+ io_bucket->write_bytes += delta > 0 ? delta : 0; -+ delta = io_curr->rchar + io_dead->rchar - io_last->rchar; -+ io_bucket->rchar += delta > 0 ? delta : 0; -+ delta = io_curr->wchar + io_dead->wchar - io_last->wchar; -+ io_bucket->wchar += delta > 0 ? delta : 0; -+ delta = io_curr->fsync + io_dead->fsync - io_last->fsync; -+ io_bucket->fsync += delta > 0 ? delta : 0; -+ -+ io_last->read_bytes = io_curr->read_bytes; -+ io_last->write_bytes = io_curr->write_bytes; -+ io_last->rchar = io_curr->rchar; -+ io_last->wchar = io_curr->wchar; -+ io_last->fsync = io_curr->fsync; -+ -+ memset(io_dead, 0, sizeof(struct io_stats)); -+} -+ -+#ifdef CONFIG_UID_SYS_STATS_DEBUG -+static void get_full_task_comm(struct task_entry *task_entry, -+ struct task_struct *task) -+{ -+ int i = 0, offset = 0, len = 0; -+ /* save one byte for terminating null character */ -+ int unused_len = MAX_TASK_COMM_LEN - TASK_COMM_LEN - 1; -+ char buf[unused_len]; -+ struct mm_struct *mm = task->mm; -+ -+ /* fill the first TASK_COMM_LEN bytes with thread name */ -+ __get_task_comm(task_entry->comm, TASK_COMM_LEN, task); -+ i = strlen(task_entry->comm); -+ while (i < TASK_COMM_LEN) -+ task_entry->comm[i++] = ' '; -+ -+ /* next the executable file name */ -+ if (mm) { -+ down_read(&mm->mmap_sem); -+ if (mm->exe_file) { -+ char *pathname = d_path(&mm->exe_file->f_path, buf, -+ unused_len); -+ -+ if (!IS_ERR(pathname)) { -+ len = strlcpy(task_entry->comm + i, pathname, -+ unused_len); -+ i += len; -+ task_entry->comm[i++] = ' '; -+ unused_len--; -+ } -+ } -+ up_read(&mm->mmap_sem); -+ } -+ unused_len -= len; -+ -+ /* fill the rest with command line argument -+ * replace each null or new line character -+ * between args in argv with whitespace */ -+ len = get_cmdline(task, buf, unused_len); -+ while (offset < len) { -+ if (buf[offset] != '\0' && buf[offset] != '\n') -+ task_entry->comm[i++] = buf[offset]; -+ else -+ task_entry->comm[i++] = ' '; -+ offset++; -+ } -+ -+ /* get rid of trailing whitespaces in case when arg is memset to -+ * zero before being reset in userspace -+ */ -+ while (task_entry->comm[i-1] == ' ') -+ i--; -+ task_entry->comm[i] = '\0'; -+} -+ -+static struct task_entry *find_task_entry(struct uid_entry *uid_entry, -+ struct task_struct *task) -+{ -+ struct task_entry *task_entry; -+ -+ hash_for_each_possible(uid_entry->task_entries, task_entry, hash, -+ task->pid) { -+ if (task->pid == task_entry->pid) { -+ /* if thread name changed, update the entire command */ -+ int len = strnchr(task_entry->comm, ' ', TASK_COMM_LEN) -+ - task_entry->comm; -+ -+ if (strncmp(task_entry->comm, task->comm, len)) -+ get_full_task_comm(task_entry, task); -+ return task_entry; -+ } -+ } -+ return NULL; -+} -+ -+static struct task_entry *find_or_register_task(struct uid_entry *uid_entry, -+ struct task_struct *task) -+{ -+ struct task_entry *task_entry; -+ pid_t pid = task->pid; -+ -+ task_entry = find_task_entry(uid_entry, task); -+ if (task_entry) -+ return task_entry; -+ -+ task_entry = kzalloc(sizeof(struct task_entry), GFP_ATOMIC); -+ if (!task_entry) -+ return NULL; -+ -+ get_full_task_comm(task_entry, task); -+ -+ task_entry->pid = pid; -+ hash_add(uid_entry->task_entries, &task_entry->hash, (unsigned int)pid); -+ -+ return task_entry; -+} -+ -+static void remove_uid_tasks(struct uid_entry *uid_entry) -+{ -+ struct task_entry *task_entry; -+ unsigned long bkt_task; -+ struct hlist_node *tmp_task; -+ -+ hash_for_each_safe(uid_entry->task_entries, bkt_task, -+ tmp_task, task_entry, hash) { -+ hash_del(&task_entry->hash); -+ kfree(task_entry); -+ } -+} -+ -+static void set_io_uid_tasks_zero(struct uid_entry *uid_entry) -+{ -+ struct task_entry *task_entry; -+ unsigned long bkt_task; -+ -+ hash_for_each(uid_entry->task_entries, bkt_task, task_entry, hash) { -+ memset(&task_entry->io[UID_STATE_TOTAL_CURR], 0, -+ sizeof(struct io_stats)); -+ } -+} -+ -+static void add_uid_tasks_io_stats(struct uid_entry *uid_entry, -+ struct task_struct *task, int slot) -+{ -+ struct task_entry *task_entry = find_or_register_task(uid_entry, task); -+ struct io_stats *task_io_slot = &task_entry->io[slot]; -+ -+ task_io_slot->read_bytes += task->ioac.read_bytes; -+ task_io_slot->write_bytes += compute_write_bytes(task); -+ task_io_slot->rchar += task->ioac.rchar; -+ task_io_slot->wchar += task->ioac.wchar; -+} -+ -+static void compute_io_uid_tasks(struct uid_entry *uid_entry) -+{ -+ struct task_entry *task_entry; -+ unsigned long bkt_task; -+ -+ hash_for_each(uid_entry->task_entries, bkt_task, task_entry, hash) { -+ compute_io_bucket_stats(&task_entry->io[uid_entry->state], -+ &task_entry->io[UID_STATE_TOTAL_CURR], -+ &task_entry->io[UID_STATE_TOTAL_LAST], -+ &task_entry->io[UID_STATE_DEAD_TASKS]); -+ } -+} -+ -+static void show_io_uid_tasks(struct seq_file *m, struct uid_entry *uid_entry) -+{ -+ struct task_entry *task_entry; -+ unsigned long bkt_task; -+ -+ hash_for_each(uid_entry->task_entries, bkt_task, task_entry, hash) { -+ /* Separated by comma because space exists in task comm */ -+ seq_printf(m, "task,%s,%lu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n", -+ task_entry->comm, -+ (unsigned long)task_entry->pid, -+ task_entry->io[UID_STATE_FOREGROUND].rchar, -+ task_entry->io[UID_STATE_FOREGROUND].wchar, -+ task_entry->io[UID_STATE_FOREGROUND].read_bytes, -+ task_entry->io[UID_STATE_FOREGROUND].write_bytes, -+ task_entry->io[UID_STATE_BACKGROUND].rchar, -+ task_entry->io[UID_STATE_BACKGROUND].wchar, -+ task_entry->io[UID_STATE_BACKGROUND].read_bytes, -+ task_entry->io[UID_STATE_BACKGROUND].write_bytes, -+ task_entry->io[UID_STATE_FOREGROUND].fsync, -+ task_entry->io[UID_STATE_BACKGROUND].fsync); -+ } -+} -+#else -+static void remove_uid_tasks(struct uid_entry *uid_entry) {}; -+static void set_io_uid_tasks_zero(struct uid_entry *uid_entry) {}; -+static void add_uid_tasks_io_stats(struct uid_entry *uid_entry, -+ struct task_struct *task, int slot) {}; -+static void compute_io_uid_tasks(struct uid_entry *uid_entry) {}; -+static void show_io_uid_tasks(struct seq_file *m, -+ struct uid_entry *uid_entry) {} -+#endif -+ - static struct uid_entry *find_uid_entry(uid_t uid) - { - struct uid_entry *uid_entry; -@@ -66,13 +319,15 @@ static struct uid_entry *find_or_register_uid(uid_t uid) - return NULL; - - uid_entry->uid = uid; -- -+#ifdef CONFIG_UID_SYS_STATS_DEBUG -+ hash_init(uid_entry->task_entries); -+#endif - hash_add(hash_table, &uid_entry->hash, uid); - - return uid_entry; - } - --static int uid_stat_show(struct seq_file *m, void *v) -+static int uid_cputime_show(struct seq_file *m, void *v) - { - struct uid_entry *uid_entry = NULL; - struct task_struct *task, *temp; -@@ -120,13 +375,13 @@ static int uid_stat_show(struct seq_file *m, void *v) - return 0; - } - --static int uid_stat_open(struct inode *inode, struct file *file) -+static int uid_cputime_open(struct inode *inode, struct file *file) - { -- return single_open(file, uid_stat_show, PDE_DATA(inode)); -+ return single_open(file, uid_cputime_show, PDE_DATA(inode)); - } - --static const struct file_operations uid_stat_fops = { -- .open = uid_stat_open, -+static const struct file_operations uid_cputime_fops = { -+ .open = uid_cputime_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -@@ -163,12 +418,14 @@ static ssize_t uid_remove_write(struct file *file, - kstrtol(end_uid, 10, &uid_end) != 0) { - return -EINVAL; - } -+ - rt_mutex_lock(&uid_lock); - - for (; uid_start <= uid_end; uid_start++) { - hash_for_each_possible_safe(hash_table, uid_entry, tmp, - hash, (uid_t)uid_start) { - if (uid_start == uid_entry->uid) { -+ remove_uid_tasks(uid_entry); - hash_del(&uid_entry->hash); - kfree(uid_entry); - } -@@ -185,6 +442,177 @@ static const struct file_operations uid_remove_fops = { - .write = uid_remove_write, - }; - -+ -+static void add_uid_io_stats(struct uid_entry *uid_entry, -+ struct task_struct *task, int slot) -+{ -+ struct io_stats *io_slot = &uid_entry->io[slot]; -+ -+ io_slot->read_bytes += task->ioac.read_bytes; -+ io_slot->write_bytes += compute_write_bytes(task); -+ io_slot->rchar += task->ioac.rchar; -+ io_slot->wchar += task->ioac.wchar; -+ -+ add_uid_tasks_io_stats(uid_entry, task, slot); -+} -+ -+static void update_io_stats_all_locked(void) -+{ -+ struct uid_entry *uid_entry = NULL; -+ struct task_struct *task, *temp; -+ struct user_namespace *user_ns = current_user_ns(); -+ unsigned long 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); -+ } -+ -+ rcu_read_lock(); -+ do_each_thread(temp, task) { -+ uid = from_kuid_munged(user_ns, task_uid(task)); -+ if (!uid_entry || uid_entry->uid != uid) -+ uid_entry = find_or_register_uid(uid); -+ if (!uid_entry) -+ continue; -+ add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR); -+ } 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); -+ } -+} -+ -+static void update_io_stats_uid_locked(struct uid_entry *uid_entry) -+{ -+ struct task_struct *task, *temp; -+ struct user_namespace *user_ns = current_user_ns(); -+ -+ memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0, -+ sizeof(struct io_stats)); -+ set_io_uid_tasks_zero(uid_entry); -+ -+ rcu_read_lock(); -+ do_each_thread(temp, task) { -+ if (from_kuid_munged(user_ns, task_uid(task)) != uid_entry->uid) -+ continue; -+ add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR); -+ } while_each_thread(temp, task); -+ rcu_read_unlock(); -+ -+ 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); -+} -+ -+ -+static int uid_io_show(struct seq_file *m, void *v) -+{ -+ struct uid_entry *uid_entry; -+ unsigned long bkt; -+ -+ rt_mutex_lock(&uid_lock); -+ -+ 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", -+ uid_entry->uid, -+ uid_entry->io[UID_STATE_FOREGROUND].rchar, -+ uid_entry->io[UID_STATE_FOREGROUND].wchar, -+ uid_entry->io[UID_STATE_FOREGROUND].read_bytes, -+ uid_entry->io[UID_STATE_FOREGROUND].write_bytes, -+ uid_entry->io[UID_STATE_BACKGROUND].rchar, -+ uid_entry->io[UID_STATE_BACKGROUND].wchar, -+ uid_entry->io[UID_STATE_BACKGROUND].read_bytes, -+ uid_entry->io[UID_STATE_BACKGROUND].write_bytes, -+ uid_entry->io[UID_STATE_FOREGROUND].fsync, -+ uid_entry->io[UID_STATE_BACKGROUND].fsync); -+ -+ show_io_uid_tasks(m, uid_entry); -+ } -+ -+ rt_mutex_unlock(&uid_lock); -+ return 0; -+} -+ -+static int uid_io_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, uid_io_show, PDE_DATA(inode)); -+} -+ -+static const struct file_operations uid_io_fops = { -+ .open = uid_io_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static int uid_procstat_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, NULL, NULL); -+} -+ -+static ssize_t uid_procstat_write(struct file *file, -+ const char __user *buffer, size_t count, loff_t *ppos) -+{ -+ struct uid_entry *uid_entry; -+ uid_t uid; -+ int argc, state; -+ char input[128]; -+ -+ if (count >= sizeof(input)) -+ return -EINVAL; -+ -+ if (copy_from_user(input, buffer, count)) -+ return -EFAULT; -+ -+ input[count] = '\0'; -+ -+ argc = sscanf(input, "%u %d", &uid, &state); -+ if (argc != 2) -+ return -EINVAL; -+ -+ if (state != UID_STATE_BACKGROUND && state != UID_STATE_FOREGROUND) -+ return -EINVAL; -+ -+ rt_mutex_lock(&uid_lock); -+ -+ uid_entry = find_or_register_uid(uid); -+ if (!uid_entry) { -+ rt_mutex_unlock(&uid_lock); -+ return -EINVAL; -+ } -+ -+ if (uid_entry->state == state) { -+ rt_mutex_unlock(&uid_lock); -+ return count; -+ } -+ -+ update_io_stats_uid_locked(uid_entry); -+ -+ uid_entry->state = state; -+ -+ rt_mutex_unlock(&uid_lock); -+ -+ return count; -+} -+ -+static const struct file_operations uid_procstat_fops = { -+ .open = uid_procstat_open, -+ .release = single_release, -+ .write = uid_procstat_write, -+}; -+ - static int process_notifier(struct notifier_block *self, - unsigned long cmd, void *v) - { -@@ -208,6 +636,8 @@ static int process_notifier(struct notifier_block *self, - uid_entry->utime += utime; - uid_entry->stime += stime; - -+ add_uid_io_stats(uid_entry, task, UID_STATE_DEAD_TASKS); -+ - exit: - rt_mutex_unlock(&uid_lock); - return NOTIFY_OK; -@@ -217,25 +647,51 @@ static struct notifier_block process_notifier_block = { - .notifier_call = process_notifier, - }; - --static int __init proc_uid_cputime_init(void) -+static int __init proc_uid_sys_stats_init(void) - { - hash_init(hash_table); - -- parent = proc_mkdir("uid_cputime", NULL); -- if (!parent) { -- pr_err("%s: failed to create proc entry\n", __func__); -- return -ENOMEM; -+ cpu_parent = proc_mkdir("uid_cputime", NULL); -+ if (!cpu_parent) { -+ pr_err("%s: failed to create uid_cputime proc entry\n", -+ __func__); -+ goto err; -+ } -+ -+ proc_create_data("remove_uid_range", 0222, cpu_parent, -+ &uid_remove_fops, NULL); -+ proc_create_data("show_uid_stat", 0444, cpu_parent, -+ &uid_cputime_fops, NULL); -+ -+ io_parent = proc_mkdir("uid_io", NULL); -+ if (!io_parent) { -+ pr_err("%s: failed to create uid_io proc entry\n", -+ __func__); -+ goto err; - } - -- proc_create_data("remove_uid_range", S_IWUGO, parent, &uid_remove_fops, -- NULL); -+ proc_create_data("stats", 0444, io_parent, -+ &uid_io_fops, NULL); - -- proc_create_data("show_uid_stat", S_IRUGO, parent, &uid_stat_fops, -- NULL); -+ proc_parent = proc_mkdir("uid_procstat", NULL); -+ if (!proc_parent) { -+ pr_err("%s: failed to create uid_procstat proc entry\n", -+ __func__); -+ goto err; -+ } -+ -+ proc_create_data("set", 0222, proc_parent, -+ &uid_procstat_fops, NULL); - - profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block); - - return 0; -+ -+err: -+ remove_proc_subtree("uid_cputime", NULL); -+ remove_proc_subtree("uid_io", NULL); -+ remove_proc_subtree("uid_procstat", NULL); -+ return -ENOMEM; - } - --early_initcall(proc_uid_cputime_init); -+early_initcall(proc_uid_sys_stats_init); diff --git a/patches/ANDROID-unconditionally-compile-sig_ok-in-struct-module.patch b/patches/ANDROID-unconditionally-compile-sig_ok-in-struct-module.patch deleted file mode 100644 index 53fa59ffe57ce821d6b07dc6c227f2c7b7bf6f39..0000000000000000000000000000000000000000 --- a/patches/ANDROID-unconditionally-compile-sig_ok-in-struct-module.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Muckle -Date: Thu, 17 Oct 2019 12:14:13 -0700 -Subject: ANDROID: unconditionally compile sig_ok in struct module - -The generic kernel image must have module signing disabled so it can -load kernel modules from all vendors. Unfortunately loading a signed -kernel module into a kernel with module signing disabled will fail -because struct module_layout (which appears in kernel modules) contains -struct module, and struct module contains the sig_ok field, which is -conditionally compiled depending on CONFIG_MODULE_SIG (module signing). - -Unconditionally compile the sig_ok field to work around this problem. - -Bug: 135940219 -Test: load a signed kernel module with module signing disabled -Change-Id: I5cc437c806f74f89c0e45ce4135136ca0c70738e -Signed-off-by: Steve Muckle ---- - include/linux/module.h | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/include/linux/module.h b/include/linux/module.h -index 6d20895e7739..6744ffe9a727 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -389,10 +389,12 @@ struct module { - const s32 *unused_gpl_crcs; - #endif - --#ifdef CONFIG_MODULE_SIG -- /* Signature was verified. */ -+ /* -+ * Signature was verified. Unconditionally compiled in Android to -+ * preserve ABI compatibility between kernels without module -+ * signing enabled and signed modules. -+ */ - bool sig_ok; --#endif - - bool async_probe_requested; - diff --git a/patches/ANDROID-update-arm64-gki_defconfig.patch b/patches/ANDROID-update-arm64-gki_defconfig.patch deleted file mode 100644 index 312dc9a2fedfd1bcf2dc561ce3ef581284929c56..0000000000000000000000000000000000000000 --- a/patches/ANDROID-update-arm64-gki_defconfig.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Greg Kroah-Hartman -Date: Mon, 23 Sep 2019 14:43:39 +0200 -Subject: ANDROID: update arm64 gki_defconfig - -Update the arm64 gki_defconfig for changes made during the merge of -upstream - -Signed-off-by: Greg Kroah-Hartman -Change-Id: I50d96aa097866a43f305c59954f1242e02d0dac6 ---- - arch/arm64/configs/gki_defconfig | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index ab1dd6d01ec8..01be7843c646 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -384,7 +384,6 @@ CONFIG_FUSE_FS=y - CONFIG_OVERLAY_FS=y - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y --CONFIG_TMPFS_POSIX_ACL=y - # CONFIG_EFIVAR_FS is not set - CONFIG_SDCARD_FS=y - CONFIG_PSTORE=y diff --git a/patches/ANDROID-update-gki_defconfig-2.patch b/patches/ANDROID-update-gki_defconfig-2.patch deleted file mode 100644 index c936b5fc71f7f978ae4c7d3fa7be2358960b4741..0000000000000000000000000000000000000000 --- a/patches/ANDROID-update-gki_defconfig-2.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Greg Kroah-Hartman -Date: Mon, 30 Sep 2019 13:31:19 +0200 -Subject: ANDROID: update gki_defconfig - -Update the default gki_defconfig now that there were some config changes -in mainline. - -Signed-off-by: Greg Kroah-Hartman -Change-Id: Iafb8e2fa2d8027b2848e93d2d39b0ea42028289b ---- - arch/arm64/configs/gki_defconfig | 1 - - arch/x86/configs/gki_defconfig | 1 - - 2 files changed, 2 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index 01be7843c646..97e0e47767e2 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -298,7 +298,6 @@ CONFIG_MEDIA_CONTROLLER=y - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set - CONFIG_DRM_VIRTIO_GPU=y --# CONFIG_LCD_CLASS_DEVICE is not set - CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_SOUND=y - CONFIG_SND=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 73d513715ce7..7890c249bca9 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -255,7 +255,6 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_DRM=y - # CONFIG_DRM_FBDEV_EMULATION is not set - CONFIG_DRM_VIRTIO_GPU=m --# CONFIG_LCD_CLASS_DEVICE is not set - CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_SOUND=y - CONFIG_SND=y diff --git a/patches/ANDROID-update-gki_defconfig.patch b/patches/ANDROID-update-gki_defconfig.patch deleted file mode 100644 index 2dbf8ec62cbff0641288400dc6688136fe02b587..0000000000000000000000000000000000000000 --- a/patches/ANDROID-update-gki_defconfig.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Greg Kroah-Hartman -Date: Thu, 19 Sep 2019 23:21:24 +0200 -Subject: ANDROID: update gki_defconfig - -The 5.4-rc1-prerelease merge changed a few config options, so update -gki_defconfig so that the build will run properly. - -Signed-off-by: Greg Kroah-Hartman -Change-Id: I8feb0a501d60005a7973b1fa2f9d34bb87b64259 ---- - arch/arm64/configs/gki_defconfig | 1 - - arch/x86/configs/gki_defconfig | 1 - - 2 files changed, 2 deletions(-) - -diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig -index f964b81a1e4b..ab1dd6d01ec8 100644 ---- a/arch/arm64/configs/gki_defconfig -+++ b/arch/arm64/configs/gki_defconfig -@@ -397,7 +397,6 @@ CONFIG_HARDENED_USERCOPY=y - CONFIG_SECURITY_SELINUX=y - CONFIG_CRYPTO_ADIANTUM=y - CONFIG_CRYPTO_MD4=y --CONFIG_CRYPTO_SHA512=y - CONFIG_CRYPTO_LZ4=y - CONFIG_CRYPTO_ZSTD=y - CONFIG_CRYPTO_ANSI_CPRNG=y -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 642729662b04..73d513715ce7 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -328,7 +328,6 @@ CONFIG_SECURITY_NETWORK=y - CONFIG_HARDENED_USERCOPY=y - CONFIG_SECURITY_SELINUX=y - CONFIG_CRYPTO_ADIANTUM=y --CONFIG_CRYPTO_SHA512=y - CONFIG_CRYPTO_LZ4=y - CONFIG_CRYPTO_ZSTD=y - CONFIG_CRYPTO_ANSI_CPRNG=y diff --git a/patches/ANDROID-usb-gadget-Fix-dependency-for-f_accessory.patch b/patches/ANDROID-usb-gadget-Fix-dependency-for-f_accessory.patch deleted file mode 100644 index 0dcd7dfc934d60af73d5c7064cbbe23e158b10af..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-Fix-dependency-for-f_accessory.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Quentin Perret -Date: Mon, 30 Sep 2019 15:27:24 +0100 -Subject: ANDROID: usb: gadget: Fix dependency for f_accessory - -The Android Accessory USB gadget functions use core HID functions. As -such, compiling with CONFIG_HID=m and CONFIG_USB_GADGET=y fails to link: - - drivers/usb/gadget/function/f_accessory.o: In function `acc_complete_send_hid_event': - f_accessory.c:(.text+0xd54): undefined reference to `hid_report_raw_event' - drivers/usb/gadget/function/f_accessory.o: In function `acc_hid_work': - f_accessory.c:(.text+0x2a98): undefined reference to `hid_destroy_device' - f_accessory.c:(.text+0x2ad4): undefined reference to `hid_allocate_device' - f_accessory.c:(.text+0x2b64): undefined reference to `hid_add_device' - f_accessory.c:(.text+0x2d04): undefined reference to `hid_destroy_device' - drivers/usb/gadget/function/f_accessory.o: In function `acc_hid_parse': - f_accessory.c:(.text+0x2e24): undefined reference to `hid_parse_report' - drivers/usb/gadget/function/f_accessory.o: In function `acc_function_bind_configfs': - f_accessory.c:(.text+0x2f8c): undefined reference to `__hid_register_driver' - drivers/usb/gadget/function/f_accessory.o: In function `acc_function_unbind': - f_accessory.c:(.text+0x3bc8): undefined reference to `hid_unregister_driver' - drivers/usb/gadget/function/f_accessory.o: In function `acc_hid_probe': - f_accessory.c:(.text+0x3ef4): undefined reference to `hid_open_report' - f_accessory.c:(.text+0x3f18): undefined reference to `hid_hw_start' - -Fix this by making the dependency on HID explicit. - -Bug: 140224784 -Fixes: 483cb5629ea7 ("ANDROID: usb: gadget: f_accessory: Add Android -Accessory function") -Signed-off-by: Quentin Perret -Change-Id: Ibd8640d7766cc7802d8275bfe3adfa007f3318fe ---- - drivers/usb/gadget/Kconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig -index 920ff2d2c557..bcd7f83c9ba0 100644 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -386,6 +386,7 @@ config USB_CONFIGFS_F_FS - config USB_CONFIGFS_F_ACC - bool "Accessory gadget" - depends on USB_CONFIGFS -+ depends on HID=y - select USB_F_ACC - help - USB gadget Accessory support diff --git a/patches/ANDROID-usb-gadget-configfs-Add-Uevent-to-notify-userspace.patch b/patches/ANDROID-usb-gadget-configfs-Add-Uevent-to-notify-userspace.patch deleted file mode 100644 index 46cce4ea032589aea4a655f58a15d8ee67e6bf0e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-configfs-Add-Uevent-to-notify-userspace.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Badhri Jagan Sridharan -Date: Mon, 15 Dec 2014 10:44:47 -0800 -Subject: ANDROID: usb: gadget: configfs: Add Uevent to notify userspace - -Android userspace UsbDeviceManager relies on the -uevents generated by the composition driver to -generate user notifications. This CL adds uevents -to be generated whenever USB changes its state -i.e. connected, disconnected, configured. - -This CL also intercepts the setup requests from -the usb_core anb routes it to the specific -usb function if required. - -Bug: 68755607 -Bug: 120441124 -Change-Id: Ib3d3a78255a532f7449dac286f776c2966caf8c1 -[badhri: Migrate to using udc uevents from upstream sysfs.] -Signed-off-by: Badhri Jagan Sridharan -[AmitP: Folded following android-4.9 commit changes into this patch - 9214c899f730 ("ANDROID: usb: gadget: configfs: handle gadget reset request for android")] -Signed-off-by: Amit Pundir -[astrachan: Folded change 5c899c9fd75d ("ANDROID: usb: gadget: configfs: - fix null ptr in android_disconnect") into this patch] -Signed-off-by: Alistair Strachan ---- - drivers/usb/gadget/Kconfig | 8 ++ - drivers/usb/gadget/configfs.c | 166 +++++++++++++++++++++++++++++++++- - 2 files changed, 171 insertions(+), 3 deletions(-) - -diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig -index 02ff850278b1..f5e82dcac583 100644 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -230,6 +230,14 @@ config USB_CONFIGFS - appropriate symbolic links. - For more information see Documentation/usb/gadget_configfs.rst. - -+config USB_CONFIGFS_UEVENT -+ bool "Uevent notification of Gadget state" -+ depends on USB_CONFIGFS -+ help -+ Enable uevent notifications to userspace when the gadget -+ state changes. The gadget can be in any of the following -+ three states: "CONNECTED/DISCONNECTED/CONFIGURED" -+ - config USB_CONFIGFS_SERIAL - bool "Generic serial bulk in/out" - depends on USB_CONFIGFS -diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c -index 025129942894..bbc166f99893 100644 ---- a/drivers/usb/gadget/configfs.c -+++ b/drivers/usb/gadget/configfs.c -@@ -10,6 +10,19 @@ - #include "u_f.h" - #include "u_os_desc.h" - -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+#include -+#include -+#include -+ -+#ifdef CONFIG_USB_CONFIGFS_F_ACC -+extern int acc_ctrlrequest(struct usb_composite_dev *cdev, -+ const struct usb_ctrlrequest *ctrl); -+void acc_disconnect(void); -+#endif -+static struct class *android_class; -+#endif -+ - int check_user_usb_string(const char *name, - struct usb_gadget_strings *stringtab_dev) - { -@@ -61,6 +74,12 @@ struct gadget_info { - bool use_os_desc; - char b_vendor_code; - char qw_sign[OS_STRING_QW_SIGN_LEN]; -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+ bool connected; -+ bool sw_connected; -+ struct work_struct work; -+ struct device *dev; -+#endif - }; - - static inline struct gadget_info *to_gadget_info(struct config_item *item) -@@ -266,7 +285,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, - - mutex_lock(&gi->lock); - -- if (!strlen(name)) { -+ if (!strlen(name) || strcmp(name, "none") == 0) { - ret = unregister_gadget(gi); - if (ret) - goto err; -@@ -1372,6 +1391,57 @@ static int configfs_composite_bind(struct usb_gadget *gadget, - return ret; - } - -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+static void android_work(struct work_struct *data) -+{ -+ struct gadget_info *gi = container_of(data, struct gadget_info, work); -+ struct usb_composite_dev *cdev = &gi->cdev; -+ char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL }; -+ char *connected[2] = { "USB_STATE=CONNECTED", NULL }; -+ char *configured[2] = { "USB_STATE=CONFIGURED", NULL }; -+ /* 0-connected 1-configured 2-disconnected*/ -+ bool status[3] = { false, false, false }; -+ unsigned long flags; -+ bool uevent_sent = false; -+ -+ spin_lock_irqsave(&cdev->lock, flags); -+ if (cdev->config) -+ status[1] = true; -+ -+ if (gi->connected != gi->sw_connected) { -+ if (gi->connected) -+ status[0] = true; -+ else -+ status[2] = true; -+ gi->sw_connected = gi->connected; -+ } -+ spin_unlock_irqrestore(&cdev->lock, flags); -+ -+ if (status[0]) { -+ kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, connected); -+ pr_info("%s: sent uevent %s\n", __func__, connected[0]); -+ uevent_sent = true; -+ } -+ -+ if (status[1]) { -+ kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, configured); -+ pr_info("%s: sent uevent %s\n", __func__, configured[0]); -+ uevent_sent = true; -+ } -+ -+ if (status[2]) { -+ kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, disconnected); -+ pr_info("%s: sent uevent %s\n", __func__, disconnected[0]); -+ uevent_sent = true; -+ } -+ -+ if (!uevent_sent) { -+ pr_info("%s: did not send uevent (%d %d %p)\n", __func__, -+ gi->connected, gi->sw_connected, cdev->config); -+ } -+} -+#endif -+ - static void configfs_composite_unbind(struct usb_gadget *gadget) - { - struct usb_composite_dev *cdev; -@@ -1391,14 +1461,91 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) - set_gadget_data(gadget, NULL); - } - -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+static int android_setup(struct usb_gadget *gadget, -+ const struct usb_ctrlrequest *c) -+{ -+ struct usb_composite_dev *cdev = get_gadget_data(gadget); -+ unsigned long flags; -+ struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); -+ int value = -EOPNOTSUPP; -+ struct usb_function_instance *fi; -+ -+ spin_lock_irqsave(&cdev->lock, flags); -+ if (!gi->connected) { -+ gi->connected = 1; -+ schedule_work(&gi->work); -+ } -+ spin_unlock_irqrestore(&cdev->lock, flags); -+ list_for_each_entry(fi, &gi->available_func, cfs_list) { -+ if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) { -+ value = fi->f->setup(fi->f, c); -+ if (value >= 0) -+ break; -+ } -+ } -+ -+#ifdef CONFIG_USB_CONFIGFS_F_ACC -+ if (value < 0) -+ value = acc_ctrlrequest(cdev, c); -+#endif -+ -+ if (value < 0) -+ value = composite_setup(gadget, c); -+ -+ spin_lock_irqsave(&cdev->lock, flags); -+ if (c->bRequest == USB_REQ_SET_CONFIGURATION && -+ cdev->config) { -+ schedule_work(&gi->work); -+ } -+ spin_unlock_irqrestore(&cdev->lock, flags); -+ -+ return value; -+} -+ -+static void android_disconnect(struct usb_gadget *gadget) -+{ -+ struct usb_composite_dev *cdev = get_gadget_data(gadget); -+ struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); -+ -+ /* FIXME: There's a race between usb_gadget_udc_stop() which is likely -+ * to set the gadget driver to NULL in the udc driver and this drivers -+ * gadget disconnect fn which likely checks for the gadget driver to -+ * be a null ptr. It happens that unbind (doing set_gadget_data(NULL)) -+ * is called before the gadget driver is set to NULL and the udc driver -+ * calls disconnect fn which results in cdev being a null ptr. -+ */ -+ if (cdev == NULL) { -+ WARN(1, "%s: gadget driver already disconnected\n", __func__); -+ return; -+ } -+ -+ /* accessory HID support can be active while the -+ accessory function is not actually enabled, -+ so we need to inform it when we are disconnected. -+ */ -+ -+#ifdef CONFIG_USB_CONFIGFS_F_ACC -+ acc_disconnect(); -+#endif -+ gi->connected = 0; -+ schedule_work(&gi->work); -+ composite_disconnect(gadget); -+} -+#endif -+ - static const struct usb_gadget_driver configfs_driver_template = { - .bind = configfs_composite_bind, - .unbind = configfs_composite_unbind, -- -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+ .setup = android_setup, -+ .reset = android_disconnect, -+ .disconnect = android_disconnect, -+#else - .setup = composite_setup, - .reset = composite_disconnect, - .disconnect = composite_disconnect, -- -+#endif - .suspend = composite_suspend, - .resume = composite_resume, - -@@ -1458,6 +1605,12 @@ static struct config_group *gadgets_make( - gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL); - gi->composite.name = gi->composite.gadget_driver.function; - -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+ INIT_WORK(&gi->work, android_work); -+ gi->dev = device_create(android_class, NULL, -+ MKDEV(0, 0), NULL, "android0"); -+#endif -+ - if (!gi->composite.gadget_driver.function) - goto err; - -@@ -1509,6 +1662,13 @@ static int __init gadget_cfs_init(void) - config_group_init(&gadget_subsys.su_group); - - ret = configfs_register_subsystem(&gadget_subsys); -+ -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+ android_class = class_create(THIS_MODULE, "android_usb"); -+ if (IS_ERR(android_class)) -+ return PTR_ERR(android_class); -+#endif -+ - return ret; - } - module_init(gadget_cfs_init); diff --git a/patches/ANDROID-usb-gadget-configfs-Add-device-attribute-to-determine-gadget-state.patch b/patches/ANDROID-usb-gadget-configfs-Add-device-attribute-to-determine-gadget-state.patch deleted file mode 100644 index 7241be4a35229ba384685422a1bd714e4facd83c..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-configfs-Add-device-attribute-to-determine-gadget-state.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Badhri Jagan Sridharan -Date: Sun, 9 Aug 2015 15:12:50 -0700 -Subject: ANDROID: usb: gadget: configfs: Add device attribute to determine - gadget state - -Android frameworks (UsbDeviceManager) relies on gadget state exported -through device attributes. This CL adds the device attribute to export -USB gadget state. - -Bug: 68755607 -Bug: 120441124 -Change-Id: Id0391810d75b58c579610fbec6e37ab22f28886d -[badhri: Migrate to using udc uevents from upstream sysfs.] -Signed-off-by: Badhri Jagan Sridharan -[AmitP: Folded following android-4.9 commit changes into this patch - Parts of e45c769fa7af ("ANDROID: usb: gadget: cleanup: fix unused variable and function warnings") -Signed-off-by: Amit Pundir ---- - drivers/usb/gadget/configfs.c | 91 ++++++++++++++++++++--------------- - 1 file changed, 52 insertions(+), 39 deletions(-) - -diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c -index da151de74e1d..b0148a449306 100644 ---- a/drivers/usb/gadget/configfs.c -+++ b/drivers/usb/gadget/configfs.c -@@ -1605,6 +1605,54 @@ static struct device_attribute *android_usb_attributes[] = { - &dev_attr_state, - NULL - }; -+ -+static int android_device_create(struct gadget_info *gi) -+{ -+ struct device_attribute **attrs; -+ struct device_attribute *attr; -+ -+ INIT_WORK(&gi->work, android_work); -+ android_device = device_create(android_class, NULL, -+ MKDEV(0, 0), NULL, "android0"); -+ if (IS_ERR(android_device)) -+ return PTR_ERR(android_device); -+ -+ dev_set_drvdata(android_device, gi); -+ -+ attrs = android_usb_attributes; -+ while ((attr = *attrs++)) { -+ int err; -+ -+ err = device_create_file(android_device, attr); -+ if (err) { -+ device_destroy(android_device->class, -+ android_device->devt); -+ return err; -+ } -+ } -+ -+ return 0; -+} -+ -+static void android_device_destroy(void) -+{ -+ struct device_attribute **attrs; -+ struct device_attribute *attr; -+ -+ attrs = android_usb_attributes; -+ while ((attr = *attrs++)) -+ device_remove_file(android_device, attr); -+ device_destroy(android_device->class, android_device->devt); -+} -+#else -+static inline int android_device_create(struct gadget_info *gi) -+{ -+ return 0; -+} -+ -+static inline void android_device_destroy(void) -+{ -+} - #endif - - static struct config_group *gadgets_make( -@@ -1612,9 +1660,6 @@ static struct config_group *gadgets_make( - const char *name) - { - struct gadget_info *gi; -- struct device_attribute **attrs; -- struct device_attribute *attr; -- int err; - - gi = kzalloc(sizeof(*gi), GFP_KERNEL); - if (!gi) -@@ -1658,37 +1703,14 @@ static struct config_group *gadgets_make( - gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL); - gi->composite.name = gi->composite.gadget_driver.function; - --#ifdef CONFIG_USB_CONFIGFS_UEVENT -- INIT_WORK(&gi->work, android_work); -- android_device = device_create(android_class, NULL, -- MKDEV(0, 0), NULL, "android0"); -- if (IS_ERR(android_device)) -+ if (!gi->composite.gadget_driver.function) - goto err; - -- dev_set_drvdata(android_device, gi); -- -- attrs = android_usb_attributes; -- while ((attr = *attrs++)) { -- err = device_create_file(android_device, attr); -- if (err) -- goto err1; -- } --#endif -- -- if (!gi->composite.gadget_driver.function) -- goto err1; -+ if (android_device_create(gi) < 0) -+ goto err; - - return &gi->group; - --err1: --#ifdef CONFIG_USB_CONFIGFS_UEVENT -- attrs = android_usb_attributes; -- while ((attr = *attrs++)) -- device_remove_file(android_device, attr); -- -- device_destroy(android_device->class, -- android_device->devt); --#endif - err: - kfree(gi); - return ERR_PTR(-ENOMEM); -@@ -1696,17 +1718,8 @@ static struct config_group *gadgets_make( - - static void gadgets_drop(struct config_group *group, struct config_item *item) - { -- struct device_attribute **attrs; -- struct device_attribute *attr; -- - config_item_put(item); -- --#ifdef CONFIG_USB_CONFIGFS_UEVENT -- attrs = android_usb_attributes; -- while ((attr = *attrs++)) -- device_remove_file(android_device, attr); -- device_destroy(android_device->class, android_device->devt); --#endif -+ android_device_destroy(); - } - - static struct configfs_group_operations gadgets_ops = { diff --git a/patches/ANDROID-usb-gadget-configfs-Add-function-devices-to-the-parent.patch b/patches/ANDROID-usb-gadget-configfs-Add-function-devices-to-the-parent.patch deleted file mode 100644 index 754cd32a1b260c0eeb505b3caabaff4d6e74fb4e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-configfs-Add-function-devices-to-the-parent.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Badhri Jagan Sridharan -Date: Fri, 27 Mar 2015 14:15:19 -0700 -Subject: ANDROID: usb: gadget: configfs: Add function devices to the parent - -Added create_function_device to create child -function devices for USB gadget functions. -Android UsbDeviceManager relies on communicating -to the devices created by the gadget functions -to implement functions such as audio_source. - -Bug: 63740241 -Bug: 68755607 -Bug: 78114713 -Bug: 120441124 -Change-Id: I0df9ad86ac32d8cdacdea164e9fed49891b45fc2 -[badhri: This is a supporting patch for other patches which have - replacements pipelined. It can be dropped when those - implementations land.] -Signed-off-by: Badhri Jagan Sridharan ---- - drivers/usb/gadget/configfs.c | 33 +++++++++++++++++++++++++++++---- - 1 file changed, 29 insertions(+), 4 deletions(-) - -diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c -index bbc166f99893..3237f450d4ab 100644 ---- a/drivers/usb/gadget/configfs.c -+++ b/drivers/usb/gadget/configfs.c -@@ -21,6 +21,18 @@ extern int acc_ctrlrequest(struct usb_composite_dev *cdev, - void acc_disconnect(void); - #endif - static struct class *android_class; -+static struct device *android_device; -+static int index; -+ -+struct device *create_function_device(char *name) -+{ -+ if (android_device && !IS_ERR(android_device)) -+ return device_create(android_class, android_device, -+ MKDEV(0, index++), NULL, name); -+ else -+ return ERR_PTR(-EINVAL); -+} -+EXPORT_SYMBOL_GPL(create_function_device); - #endif - - int check_user_usb_string(const char *name, -@@ -1418,19 +1430,22 @@ static void android_work(struct work_struct *data) - spin_unlock_irqrestore(&cdev->lock, flags); - - if (status[0]) { -- kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, connected); -+ kobject_uevent_env(&android_device->kobj, -+ KOBJ_CHANGE, connected); - pr_info("%s: sent uevent %s\n", __func__, connected[0]); - uevent_sent = true; - } - - if (status[1]) { -- kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, configured); -+ kobject_uevent_env(&android_device->kobj, -+ KOBJ_CHANGE, configured); - pr_info("%s: sent uevent %s\n", __func__, configured[0]); - uevent_sent = true; - } - - if (status[2]) { -- kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, disconnected); -+ kobject_uevent_env(&android_device->kobj, -+ KOBJ_CHANGE, disconnected); - pr_info("%s: sent uevent %s\n", __func__, disconnected[0]); - uevent_sent = true; - } -@@ -1607,8 +1622,10 @@ static struct config_group *gadgets_make( - - #ifdef CONFIG_USB_CONFIGFS_UEVENT - INIT_WORK(&gi->work, android_work); -- gi->dev = device_create(android_class, NULL, -+ android_device = device_create(android_class, NULL, - MKDEV(0, 0), NULL, "android0"); -+ if (IS_ERR(android_device)) -+ goto err; - #endif - - if (!gi->composite.gadget_driver.function) -@@ -1623,6 +1640,9 @@ static struct config_group *gadgets_make( - static void gadgets_drop(struct config_group *group, struct config_item *item) - { - config_item_put(item); -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+ device_destroy(android_device->class, android_device->devt); -+#endif - } - - static struct configfs_group_operations gadgets_ops = { -@@ -1676,5 +1696,10 @@ module_init(gadget_cfs_init); - static void __exit gadget_cfs_exit(void) - { - configfs_unregister_subsystem(&gadget_subsys); -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+ if (!IS_ERR(android_class)) -+ class_destroy(android_class); -+#endif -+ - } - module_exit(gadget_cfs_exit); diff --git a/patches/ANDROID-usb-gadget-configfs-Add-state-attribute-to-android_device.patch b/patches/ANDROID-usb-gadget-configfs-Add-state-attribute-to-android_device.patch deleted file mode 100644 index b0829d2397f7d07a00fdffa41f54b19884340ced..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-configfs-Add-state-attribute-to-android_device.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Badhri Jagan Sridharan -Date: Tue, 14 Jul 2015 15:46:11 -0700 -Subject: ANDROID: usb: gadget: configfs: Add "state" attribute to - android_device - -Added a device attribute to android_device to -determine USB_GADGET's state - -Bug: 68755607 -Bug: 120441124 -Change-Id: I17f8903120df96bf2f4bf441940b53a87b818230 -[badhri: Migrate to using udc uevents from upstream sysfs.] -Signed-off-by: Badhri Jagan Sridharan ---- - drivers/usb/gadget/configfs.c | 66 ++++++++++++++++++++++++++++++++++- - 1 file changed, 65 insertions(+), 1 deletion(-) - -diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c -index 3237f450d4ab..da151de74e1d 100644 ---- a/drivers/usb/gadget/configfs.c -+++ b/drivers/usb/gadget/configfs.c -@@ -1572,11 +1572,49 @@ static const struct usb_gadget_driver configfs_driver_template = { - .match_existing_only = 1, - }; - -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+static ssize_t state_show(struct device *pdev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct gadget_info *dev = dev_get_drvdata(pdev); -+ struct usb_composite_dev *cdev; -+ char *state = "DISCONNECTED"; -+ unsigned long flags; -+ -+ if (!dev) -+ goto out; -+ -+ cdev = &dev->cdev; -+ -+ if (!cdev) -+ goto out; -+ -+ spin_lock_irqsave(&cdev->lock, flags); -+ if (cdev->config) -+ state = "CONFIGURED"; -+ else if (dev->connected) -+ state = "CONNECTED"; -+ spin_unlock_irqrestore(&cdev->lock, flags); -+out: -+ return sprintf(buf, "%s\n", state); -+} -+ -+static DEVICE_ATTR(state, S_IRUGO, state_show, NULL); -+ -+static struct device_attribute *android_usb_attributes[] = { -+ &dev_attr_state, -+ NULL -+}; -+#endif -+ - static struct config_group *gadgets_make( - struct config_group *group, - const char *name) - { - struct gadget_info *gi; -+ struct device_attribute **attrs; -+ struct device_attribute *attr; -+ int err; - - gi = kzalloc(sizeof(*gi), GFP_KERNEL); - if (!gi) -@@ -1626,12 +1664,31 @@ static struct config_group *gadgets_make( - MKDEV(0, 0), NULL, "android0"); - if (IS_ERR(android_device)) - goto err; -+ -+ dev_set_drvdata(android_device, gi); -+ -+ attrs = android_usb_attributes; -+ while ((attr = *attrs++)) { -+ err = device_create_file(android_device, attr); -+ if (err) -+ goto err1; -+ } - #endif - - if (!gi->composite.gadget_driver.function) -- goto err; -+ goto err1; - - return &gi->group; -+ -+err1: -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+ attrs = android_usb_attributes; -+ while ((attr = *attrs++)) -+ device_remove_file(android_device, attr); -+ -+ device_destroy(android_device->class, -+ android_device->devt); -+#endif - err: - kfree(gi); - return ERR_PTR(-ENOMEM); -@@ -1639,8 +1696,15 @@ static struct config_group *gadgets_make( - - static void gadgets_drop(struct config_group *group, struct config_item *item) - { -+ struct device_attribute **attrs; -+ struct device_attribute *attr; -+ - config_item_put(item); -+ - #ifdef CONFIG_USB_CONFIGFS_UEVENT -+ attrs = android_usb_attributes; -+ while ((attr = *attrs++)) -+ device_remove_file(android_device, attr); - device_destroy(android_device->class, android_device->devt); - #endif - } diff --git a/patches/ANDROID-usb-gadget-configfs-Add-usb_function-ptr-to-fi-struct.patch b/patches/ANDROID-usb-gadget-configfs-Add-usb_function-ptr-to-fi-struct.patch deleted file mode 100644 index 012f790e79eeee95bb9d0a594cde03a70fb77d30..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-configfs-Add-usb_function-ptr-to-fi-struct.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Badhri Jagan Sridharan -Date: Mon, 15 Dec 2014 16:42:27 -0800 -Subject: ANDROID: usb: gadget: configfs: Add usb_function ptr to fi struct - -Add a pointer to the usb_function inside the -usb_function_instance structure to service -functions specific setup requests even before -the function gets added to the usb_gadget - -Bug: 63740241 -Bug: 68755607 -Bug: 78114713 -Bug: 120441124 -Change-Id: I6f457006f6c5516cc6986ec2acdf5b1ecf259d0c -[badhri: This is a supporting patch for other patches which have - replacements pipelined. It can be dropped when those - implementations land.] -Signed-off-by: Badhri Jagan Sridharan ---- - include/linux/usb/composite.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h -index 8675e145ea8b..af4396cc4ea8 100644 ---- a/include/linux/usb/composite.h -+++ b/include/linux/usb/composite.h -@@ -587,6 +587,7 @@ struct usb_function_instance { - struct config_group group; - struct list_head cfs_list; - struct usb_function_driver *fd; -+ struct usb_function *f; - int (*set_inst_name)(struct usb_function_instance *inst, - const char *name); - void (*free_func_inst)(struct usb_function_instance *inst); diff --git a/patches/ANDROID-usb-gadget-f_accessory-Add-Android-Accessory-function.patch b/patches/ANDROID-usb-gadget-f_accessory-Add-Android-Accessory-function.patch deleted file mode 100644 index 525978f38670178cafb089641adc60bdbfd9313e..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-f_accessory-Add-Android-Accessory-function.patch +++ /dev/null @@ -1,1625 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benoit Goby -Date: Mon, 19 Dec 2011 14:39:37 -0800 -Subject: ANDROID: usb: gadget: f_accessory: Add Android Accessory function - -USB accessory mode allows users to connect USB host hardware -specifically designed for Android-powered devices. The accessories -must adhere to the Android accessory protocol outlined in the -http://accessories.android.com documentation. This allows -Android devices that cannot act as a USB host to still interact with -USB hardware. When an Android device is in USB accessory mode, the -attached Android USB accessory acts as the host, provides power -to the USB bus, and enumerates connected devices. - -Bug: 63740241 -Bug: 120441124 -Change-Id: I67964b50d278f3c0471d47efbb7b0973a3502681 -[badhri: f_accessory is being migrated to userspace.] -Signed-off-by: Mike Lockwood -[AmitP: Folded following android-4.9 commit changes into this patch - ceb2f0aac624 ("ANDROID: usb: gadget: accessory: Fix section mismatch") - Parts of e27543931009 ("ANDROID: usb: gadget: Fixes and hacks to make android usb gadget compile on 3.8") - 1b07ec751563 ("ANDROID: drivers: usb: gadget: 64-bit related type fixes")] -Signed-off-by: Amit Pundir -[astrachan: Folded the following changes into this patch: - 9d5891d516e2 ("ANDROID: usb: gadget: f_accessory: Add ACCESSORY_SET_AUDIO_MODE control request and ioctl") - dc66cfce9622 ("ANDROID: usb: gadget: f_accessory: Add support for HID input devices") - 5f1ac9c2871b ("ANDROID: usb: gadget: f_accessory: move userspace interface to uapi") - 9a6241722cd8 ("ANDROID: usb: gadget: f_accessory: Enabled Zero Length Packet (ZLP) for acc_write") - 31a0ecd5a825 ("ANDROID: usb: gadget: f_accessory: check for accessory device before disconnecting HIDs") - 580721fa6cbc ("ANDROID: usb: gadget: f_accessory: Migrate to USB_FUNCTION API") - 7f407172fb28 ("ANDROID: usb: gadget: f_accessory: Fix for UsbAccessory clean unbind.") - ebc98ac5a22f ("ANDROID: usb: gadget: f_accessory: fix false disconnect due to a signal sent to the reading process") - 71c6dc5ffdab ("ANDROID: usb: gadget: f_accessory: assign no-op request complete callbacks") - 675047ee68e9 ("ANDROID: usb: gadget: f_accessory: Move gadget functions code") - b2bedaa5c7df ("CHROMIUM: usb: gadget: f_accessory: add .raw_request callback")] -Signed-off-by: Alistair Strachan ---- - drivers/usb/gadget/Kconfig | 10 + - drivers/usb/gadget/function/Makefile | 2 + - drivers/usb/gadget/function/f_accessory.c | 1352 +++++++++++++++++++++ - include/linux/usb/f_accessory.h | 23 + - include/uapi/linux/usb/f_accessory.h | 146 +++ - 5 files changed, 1533 insertions(+) - create mode 100644 drivers/usb/gadget/function/f_accessory.c - create mode 100644 include/linux/usb/f_accessory.h - create mode 100644 include/uapi/linux/usb/f_accessory.h - -diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig -index f5e82dcac583..7749fb1decb0 100644 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -216,6 +216,9 @@ config USB_F_PRINTER - config USB_F_TCM - tristate - -+config USB_F_ACC -+ tristate -+ - # this first set of drivers all depend on bulk-capable hardware. - - config USB_CONFIGFS -@@ -377,6 +380,13 @@ config USB_CONFIGFS_F_FS - implemented in kernel space (for instance Ethernet, serial or - mass storage) and other are implemented in user space. - -+config USB_CONFIGFS_F_ACC -+ bool "Accessory gadget" -+ depends on USB_CONFIGFS -+ select USB_F_ACC -+ help -+ USB gadget Accessory support -+ - config USB_CONFIGFS_F_UAC1 - bool "Audio Class 1.0" - depends on USB_CONFIGFS -diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile -index 5d3a6cf02218..2305360e5f22 100644 ---- a/drivers/usb/gadget/function/Makefile -+++ b/drivers/usb/gadget/function/Makefile -@@ -50,3 +50,5 @@ usb_f_printer-y := f_printer.o - obj-$(CONFIG_USB_F_PRINTER) += usb_f_printer.o - usb_f_tcm-y := f_tcm.o - obj-$(CONFIG_USB_F_TCM) += usb_f_tcm.o -+usb_f_accessory-y := f_accessory.o -+obj-$(CONFIG_USB_F_ACC) += usb_f_accessory.o -diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c -new file mode 100644 -index 000000000000..7aa2656a2328 ---- /dev/null -+++ b/drivers/usb/gadget/function/f_accessory.c -@@ -0,0 +1,1352 @@ -+/* -+ * Gadget Function Driver for Android USB accessories -+ * -+ * Copyright (C) 2011 Google, Inc. -+ * Author: Mike Lockwood -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+/* #define DEBUG */ -+/* #define VERBOSE_DEBUG */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define MAX_INST_NAME_LEN 40 -+#define BULK_BUFFER_SIZE 16384 -+#define ACC_STRING_SIZE 256 -+ -+#define PROTOCOL_VERSION 2 -+ -+/* String IDs */ -+#define INTERFACE_STRING_INDEX 0 -+ -+/* number of tx and rx requests to allocate */ -+#define TX_REQ_MAX 4 -+#define RX_REQ_MAX 2 -+ -+struct acc_hid_dev { -+ struct list_head list; -+ struct hid_device *hid; -+ struct acc_dev *dev; -+ /* accessory defined ID */ -+ int id; -+ /* HID report descriptor */ -+ u8 *report_desc; -+ /* length of HID report descriptor */ -+ int report_desc_len; -+ /* number of bytes of report_desc we have received so far */ -+ int report_desc_offset; -+}; -+ -+struct acc_dev { -+ struct usb_function function; -+ struct usb_composite_dev *cdev; -+ spinlock_t lock; -+ -+ struct usb_ep *ep_in; -+ struct usb_ep *ep_out; -+ -+ /* online indicates state of function_set_alt & function_unbind -+ * set to 1 when we connect -+ */ -+ int online:1; -+ -+ /* disconnected indicates state of open & release -+ * Set to 1 when we disconnect. -+ * Not cleared until our file is closed. -+ */ -+ int disconnected:1; -+ -+ /* strings sent by the host */ -+ char manufacturer[ACC_STRING_SIZE]; -+ char model[ACC_STRING_SIZE]; -+ char description[ACC_STRING_SIZE]; -+ char version[ACC_STRING_SIZE]; -+ char uri[ACC_STRING_SIZE]; -+ char serial[ACC_STRING_SIZE]; -+ -+ /* for acc_complete_set_string */ -+ int string_index; -+ -+ /* set to 1 if we have a pending start request */ -+ int start_requested; -+ -+ int audio_mode; -+ -+ /* synchronize access to our device file */ -+ atomic_t open_excl; -+ -+ struct list_head tx_idle; -+ -+ wait_queue_head_t read_wq; -+ wait_queue_head_t write_wq; -+ struct usb_request *rx_req[RX_REQ_MAX]; -+ int rx_done; -+ -+ /* delayed work for handling ACCESSORY_START */ -+ struct delayed_work start_work; -+ -+ /* worker for registering and unregistering hid devices */ -+ struct work_struct hid_work; -+ -+ /* list of active HID devices */ -+ struct list_head hid_list; -+ -+ /* list of new HID devices to register */ -+ struct list_head new_hid_list; -+ -+ /* list of dead HID devices to unregister */ -+ struct list_head dead_hid_list; -+}; -+ -+static struct usb_interface_descriptor acc_interface_desc = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0, -+ .bNumEndpoints = 2, -+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, -+ .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, -+ .bInterfaceProtocol = 0, -+}; -+ -+static struct usb_endpoint_descriptor acc_highspeed_in_desc = { -+ .bLength = USB_DT_ENDPOINT_SIZE, -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = USB_DIR_IN, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ .wMaxPacketSize = __constant_cpu_to_le16(512), -+}; -+ -+static struct usb_endpoint_descriptor acc_highspeed_out_desc = { -+ .bLength = USB_DT_ENDPOINT_SIZE, -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = USB_DIR_OUT, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ .wMaxPacketSize = __constant_cpu_to_le16(512), -+}; -+ -+static struct usb_endpoint_descriptor acc_fullspeed_in_desc = { -+ .bLength = USB_DT_ENDPOINT_SIZE, -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = USB_DIR_IN, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+}; -+ -+static struct usb_endpoint_descriptor acc_fullspeed_out_desc = { -+ .bLength = USB_DT_ENDPOINT_SIZE, -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = USB_DIR_OUT, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+}; -+ -+static struct usb_descriptor_header *fs_acc_descs[] = { -+ (struct usb_descriptor_header *) &acc_interface_desc, -+ (struct usb_descriptor_header *) &acc_fullspeed_in_desc, -+ (struct usb_descriptor_header *) &acc_fullspeed_out_desc, -+ NULL, -+}; -+ -+static struct usb_descriptor_header *hs_acc_descs[] = { -+ (struct usb_descriptor_header *) &acc_interface_desc, -+ (struct usb_descriptor_header *) &acc_highspeed_in_desc, -+ (struct usb_descriptor_header *) &acc_highspeed_out_desc, -+ NULL, -+}; -+ -+static struct usb_string acc_string_defs[] = { -+ [INTERFACE_STRING_INDEX].s = "Android Accessory Interface", -+ { }, /* end of list */ -+}; -+ -+static struct usb_gadget_strings acc_string_table = { -+ .language = 0x0409, /* en-US */ -+ .strings = acc_string_defs, -+}; -+ -+static struct usb_gadget_strings *acc_strings[] = { -+ &acc_string_table, -+ NULL, -+}; -+ -+/* temporary variable used between acc_open() and acc_gadget_bind() */ -+static struct acc_dev *_acc_dev; -+ -+struct acc_instance { -+ struct usb_function_instance func_inst; -+ const char *name; -+}; -+ -+static inline struct acc_dev *func_to_dev(struct usb_function *f) -+{ -+ return container_of(f, struct acc_dev, function); -+} -+ -+static struct usb_request *acc_request_new(struct usb_ep *ep, int buffer_size) -+{ -+ struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); -+ -+ if (!req) -+ return NULL; -+ -+ /* now allocate buffers for the requests */ -+ req->buf = kmalloc(buffer_size, GFP_KERNEL); -+ if (!req->buf) { -+ usb_ep_free_request(ep, req); -+ return NULL; -+ } -+ -+ return req; -+} -+ -+static void acc_request_free(struct usb_request *req, struct usb_ep *ep) -+{ -+ if (req) { -+ kfree(req->buf); -+ usb_ep_free_request(ep, req); -+ } -+} -+ -+/* add a request to the tail of a list */ -+static void req_put(struct acc_dev *dev, struct list_head *head, -+ struct usb_request *req) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ list_add_tail(&req->list, head); -+ spin_unlock_irqrestore(&dev->lock, flags); -+} -+ -+/* remove a request from the head of a list */ -+static struct usb_request *req_get(struct acc_dev *dev, struct list_head *head) -+{ -+ unsigned long flags; -+ struct usb_request *req; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ if (list_empty(head)) { -+ req = 0; -+ } else { -+ req = list_first_entry(head, struct usb_request, list); -+ list_del(&req->list); -+ } -+ spin_unlock_irqrestore(&dev->lock, flags); -+ return req; -+} -+ -+static void acc_set_disconnected(struct acc_dev *dev) -+{ -+ dev->disconnected = 1; -+} -+ -+static void acc_complete_in(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct acc_dev *dev = _acc_dev; -+ -+ if (req->status == -ESHUTDOWN) { -+ pr_debug("acc_complete_in set disconnected"); -+ acc_set_disconnected(dev); -+ } -+ -+ req_put(dev, &dev->tx_idle, req); -+ -+ wake_up(&dev->write_wq); -+} -+ -+static void acc_complete_out(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct acc_dev *dev = _acc_dev; -+ -+ dev->rx_done = 1; -+ if (req->status == -ESHUTDOWN) { -+ pr_debug("acc_complete_out set disconnected"); -+ acc_set_disconnected(dev); -+ } -+ -+ wake_up(&dev->read_wq); -+} -+ -+static void acc_complete_set_string(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct acc_dev *dev = ep->driver_data; -+ char *string_dest = NULL; -+ int length = req->actual; -+ -+ if (req->status != 0) { -+ pr_err("acc_complete_set_string, err %d\n", req->status); -+ return; -+ } -+ -+ switch (dev->string_index) { -+ case ACCESSORY_STRING_MANUFACTURER: -+ string_dest = dev->manufacturer; -+ break; -+ case ACCESSORY_STRING_MODEL: -+ string_dest = dev->model; -+ break; -+ case ACCESSORY_STRING_DESCRIPTION: -+ string_dest = dev->description; -+ break; -+ case ACCESSORY_STRING_VERSION: -+ string_dest = dev->version; -+ break; -+ case ACCESSORY_STRING_URI: -+ string_dest = dev->uri; -+ break; -+ case ACCESSORY_STRING_SERIAL: -+ string_dest = dev->serial; -+ break; -+ } -+ if (string_dest) { -+ unsigned long flags; -+ -+ if (length >= ACC_STRING_SIZE) -+ length = ACC_STRING_SIZE - 1; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ memcpy(string_dest, req->buf, length); -+ /* ensure zero termination */ -+ string_dest[length] = 0; -+ spin_unlock_irqrestore(&dev->lock, flags); -+ } else { -+ pr_err("unknown accessory string index %d\n", -+ dev->string_index); -+ } -+} -+ -+static void acc_complete_set_hid_report_desc(struct usb_ep *ep, -+ struct usb_request *req) -+{ -+ struct acc_hid_dev *hid = req->context; -+ struct acc_dev *dev = hid->dev; -+ int length = req->actual; -+ -+ if (req->status != 0) { -+ pr_err("acc_complete_set_hid_report_desc, err %d\n", -+ req->status); -+ return; -+ } -+ -+ memcpy(hid->report_desc + hid->report_desc_offset, req->buf, length); -+ hid->report_desc_offset += length; -+ if (hid->report_desc_offset == hid->report_desc_len) { -+ /* After we have received the entire report descriptor -+ * we schedule work to initialize the HID device -+ */ -+ schedule_work(&dev->hid_work); -+ } -+} -+ -+static void acc_complete_send_hid_event(struct usb_ep *ep, -+ struct usb_request *req) -+{ -+ struct acc_hid_dev *hid = req->context; -+ int length = req->actual; -+ -+ if (req->status != 0) { -+ pr_err("acc_complete_send_hid_event, err %d\n", req->status); -+ return; -+ } -+ -+ hid_report_raw_event(hid->hid, HID_INPUT_REPORT, req->buf, length, 1); -+} -+ -+static int acc_hid_parse(struct hid_device *hid) -+{ -+ struct acc_hid_dev *hdev = hid->driver_data; -+ -+ hid_parse_report(hid, hdev->report_desc, hdev->report_desc_len); -+ return 0; -+} -+ -+static int acc_hid_start(struct hid_device *hid) -+{ -+ return 0; -+} -+ -+static void acc_hid_stop(struct hid_device *hid) -+{ -+} -+ -+static int acc_hid_open(struct hid_device *hid) -+{ -+ return 0; -+} -+ -+static void acc_hid_close(struct hid_device *hid) -+{ -+} -+ -+static int acc_hid_raw_request(struct hid_device *hid, unsigned char reportnum, -+ __u8 *buf, size_t len, unsigned char rtype, int reqtype) -+{ -+ return 0; -+} -+ -+static struct hid_ll_driver acc_hid_ll_driver = { -+ .parse = acc_hid_parse, -+ .start = acc_hid_start, -+ .stop = acc_hid_stop, -+ .open = acc_hid_open, -+ .close = acc_hid_close, -+ .raw_request = acc_hid_raw_request, -+}; -+ -+static struct acc_hid_dev *acc_hid_new(struct acc_dev *dev, -+ int id, int desc_len) -+{ -+ struct acc_hid_dev *hdev; -+ -+ hdev = kzalloc(sizeof(*hdev), GFP_ATOMIC); -+ if (!hdev) -+ return NULL; -+ hdev->report_desc = kzalloc(desc_len, GFP_ATOMIC); -+ if (!hdev->report_desc) { -+ kfree(hdev); -+ return NULL; -+ } -+ hdev->dev = dev; -+ hdev->id = id; -+ hdev->report_desc_len = desc_len; -+ -+ return hdev; -+} -+ -+static struct acc_hid_dev *acc_hid_get(struct list_head *list, int id) -+{ -+ struct acc_hid_dev *hid; -+ -+ list_for_each_entry(hid, list, list) { -+ if (hid->id == id) -+ return hid; -+ } -+ return NULL; -+} -+ -+static int acc_register_hid(struct acc_dev *dev, int id, int desc_length) -+{ -+ struct acc_hid_dev *hid; -+ unsigned long flags; -+ -+ /* report descriptor length must be > 0 */ -+ if (desc_length <= 0) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ /* replace HID if one already exists with this ID */ -+ hid = acc_hid_get(&dev->hid_list, id); -+ if (!hid) -+ hid = acc_hid_get(&dev->new_hid_list, id); -+ if (hid) -+ list_move(&hid->list, &dev->dead_hid_list); -+ -+ hid = acc_hid_new(dev, id, desc_length); -+ if (!hid) { -+ spin_unlock_irqrestore(&dev->lock, flags); -+ return -ENOMEM; -+ } -+ -+ list_add(&hid->list, &dev->new_hid_list); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ /* schedule work to register the HID device */ -+ schedule_work(&dev->hid_work); -+ return 0; -+} -+ -+static int acc_unregister_hid(struct acc_dev *dev, int id) -+{ -+ struct acc_hid_dev *hid; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ hid = acc_hid_get(&dev->hid_list, id); -+ if (!hid) -+ hid = acc_hid_get(&dev->new_hid_list, id); -+ if (!hid) { -+ spin_unlock_irqrestore(&dev->lock, flags); -+ return -EINVAL; -+ } -+ -+ list_move(&hid->list, &dev->dead_hid_list); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ schedule_work(&dev->hid_work); -+ return 0; -+} -+ -+static int create_bulk_endpoints(struct acc_dev *dev, -+ struct usb_endpoint_descriptor *in_desc, -+ struct usb_endpoint_descriptor *out_desc) -+{ -+ struct usb_composite_dev *cdev = dev->cdev; -+ struct usb_request *req; -+ struct usb_ep *ep; -+ int i; -+ -+ DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); -+ -+ ep = usb_ep_autoconfig(cdev->gadget, in_desc); -+ if (!ep) { -+ DBG(cdev, "usb_ep_autoconfig for ep_in failed\n"); -+ return -ENODEV; -+ } -+ DBG(cdev, "usb_ep_autoconfig for ep_in got %s\n", ep->name); -+ ep->driver_data = dev; /* claim the endpoint */ -+ dev->ep_in = ep; -+ -+ ep = usb_ep_autoconfig(cdev->gadget, out_desc); -+ if (!ep) { -+ DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); -+ return -ENODEV; -+ } -+ DBG(cdev, "usb_ep_autoconfig for ep_out got %s\n", ep->name); -+ ep->driver_data = dev; /* claim the endpoint */ -+ dev->ep_out = ep; -+ -+ /* now allocate requests for our endpoints */ -+ for (i = 0; i < TX_REQ_MAX; i++) { -+ req = acc_request_new(dev->ep_in, BULK_BUFFER_SIZE); -+ if (!req) -+ goto fail; -+ req->complete = acc_complete_in; -+ req_put(dev, &dev->tx_idle, req); -+ } -+ for (i = 0; i < RX_REQ_MAX; i++) { -+ req = acc_request_new(dev->ep_out, BULK_BUFFER_SIZE); -+ if (!req) -+ goto fail; -+ req->complete = acc_complete_out; -+ dev->rx_req[i] = req; -+ } -+ -+ return 0; -+ -+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++) -+ acc_request_free(dev->rx_req[i], dev->ep_out); -+ return -1; -+} -+ -+static ssize_t acc_read(struct file *fp, char __user *buf, -+ size_t count, loff_t *pos) -+{ -+ struct acc_dev *dev = fp->private_data; -+ struct usb_request *req; -+ ssize_t r = count; -+ unsigned xfer; -+ int ret = 0; -+ -+ pr_debug("acc_read(%zu)\n", count); -+ -+ if (dev->disconnected) { -+ pr_debug("acc_read disconnected"); -+ return -ENODEV; -+ } -+ -+ if (count > BULK_BUFFER_SIZE) -+ count = BULK_BUFFER_SIZE; -+ -+ /* we will block until we're online */ -+ pr_debug("acc_read: waiting for online\n"); -+ ret = wait_event_interruptible(dev->read_wq, dev->online); -+ if (ret < 0) { -+ r = ret; -+ goto done; -+ } -+ -+ if (dev->rx_done) { -+ // last req cancelled. try to get it. -+ req = dev->rx_req[0]; -+ goto copy_data; -+ } -+ -+requeue_req: -+ /* queue a request */ -+ req = dev->rx_req[0]; -+ req->length = count; -+ dev->rx_done = 0; -+ ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL); -+ if (ret < 0) { -+ r = -EIO; -+ goto done; -+ } else { -+ pr_debug("rx %p queue\n", req); -+ } -+ -+ /* wait for a request to complete */ -+ ret = wait_event_interruptible(dev->read_wq, dev->rx_done); -+ if (ret < 0) { -+ r = ret; -+ ret = usb_ep_dequeue(dev->ep_out, req); -+ if (ret != 0) { -+ // cancel failed. There can be a data already received. -+ // it will be retrieved in the next read. -+ pr_debug("acc_read: cancelling failed %d", ret); -+ } -+ goto done; -+ } -+ -+copy_data: -+ dev->rx_done = 0; -+ if (dev->online) { -+ /* If we got a 0-len packet, throw it back and try again. */ -+ if (req->actual == 0) -+ goto requeue_req; -+ -+ pr_debug("rx %p %u\n", req, req->actual); -+ xfer = (req->actual < count) ? req->actual : count; -+ r = xfer; -+ if (copy_to_user(buf, req->buf, xfer)) -+ r = -EFAULT; -+ } else -+ r = -EIO; -+ -+done: -+ pr_debug("acc_read returning %zd\n", r); -+ return r; -+} -+ -+static ssize_t acc_write(struct file *fp, const char __user *buf, -+ size_t count, loff_t *pos) -+{ -+ struct acc_dev *dev = fp->private_data; -+ struct usb_request *req = 0; -+ ssize_t r = count; -+ unsigned xfer; -+ int ret; -+ -+ pr_debug("acc_write(%zu)\n", count); -+ -+ if (!dev->online || dev->disconnected) { -+ pr_debug("acc_write disconnected or not online"); -+ return -ENODEV; -+ } -+ -+ while (count > 0) { -+ if (!dev->online) { -+ pr_debug("acc_write dev->error\n"); -+ r = -EIO; -+ break; -+ } -+ -+ /* get an idle tx request to use */ -+ req = 0; -+ ret = wait_event_interruptible(dev->write_wq, -+ ((req = req_get(dev, &dev->tx_idle)) || !dev->online)); -+ if (!req) { -+ r = ret; -+ break; -+ } -+ -+ if (count > BULK_BUFFER_SIZE) { -+ xfer = BULK_BUFFER_SIZE; -+ /* ZLP, They will be more TX requests so not yet. */ -+ req->zero = 0; -+ } else { -+ xfer = count; -+ /* If the data length is a multple of the -+ * maxpacket size then send a zero length packet(ZLP). -+ */ -+ req->zero = ((xfer % dev->ep_in->maxpacket) == 0); -+ } -+ if (copy_from_user(req->buf, buf, xfer)) { -+ r = -EFAULT; -+ break; -+ } -+ -+ req->length = xfer; -+ ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); -+ if (ret < 0) { -+ pr_debug("acc_write: xfer error %d\n", ret); -+ r = -EIO; -+ break; -+ } -+ -+ buf += xfer; -+ count -= xfer; -+ -+ /* zero this so we don't try to free it on error exit */ -+ req = 0; -+ } -+ -+ if (req) -+ req_put(dev, &dev->tx_idle, req); -+ -+ pr_debug("acc_write returning %zd\n", r); -+ return r; -+} -+ -+static long acc_ioctl(struct file *fp, unsigned code, unsigned long value) -+{ -+ struct acc_dev *dev = fp->private_data; -+ char *src = NULL; -+ int ret; -+ -+ switch (code) { -+ case ACCESSORY_GET_STRING_MANUFACTURER: -+ src = dev->manufacturer; -+ break; -+ case ACCESSORY_GET_STRING_MODEL: -+ src = dev->model; -+ break; -+ case ACCESSORY_GET_STRING_DESCRIPTION: -+ src = dev->description; -+ break; -+ case ACCESSORY_GET_STRING_VERSION: -+ src = dev->version; -+ break; -+ case ACCESSORY_GET_STRING_URI: -+ src = dev->uri; -+ break; -+ case ACCESSORY_GET_STRING_SERIAL: -+ src = dev->serial; -+ break; -+ case ACCESSORY_IS_START_REQUESTED: -+ return dev->start_requested; -+ case ACCESSORY_GET_AUDIO_MODE: -+ return dev->audio_mode; -+ } -+ if (!src) -+ return -EINVAL; -+ -+ ret = strlen(src) + 1; -+ if (copy_to_user((void __user *)value, src, ret)) -+ ret = -EFAULT; -+ return ret; -+} -+ -+static int acc_open(struct inode *ip, struct file *fp) -+{ -+ printk(KERN_INFO "acc_open\n"); -+ if (atomic_xchg(&_acc_dev->open_excl, 1)) -+ return -EBUSY; -+ -+ _acc_dev->disconnected = 0; -+ fp->private_data = _acc_dev; -+ return 0; -+} -+ -+static int acc_release(struct inode *ip, struct file *fp) -+{ -+ printk(KERN_INFO "acc_release\n"); -+ -+ WARN_ON(!atomic_xchg(&_acc_dev->open_excl, 0)); -+ /* indicate that we are disconnected -+ * still could be online so don't touch online flag -+ */ -+ _acc_dev->disconnected = 1; -+ return 0; -+} -+ -+/* file operations for /dev/usb_accessory */ -+static const struct file_operations acc_fops = { -+ .owner = THIS_MODULE, -+ .read = acc_read, -+ .write = acc_write, -+ .unlocked_ioctl = acc_ioctl, -+ .open = acc_open, -+ .release = acc_release, -+}; -+ -+static int acc_hid_probe(struct hid_device *hdev, -+ const struct hid_device_id *id) -+{ -+ int ret; -+ -+ ret = hid_parse(hdev); -+ if (ret) -+ return ret; -+ return hid_hw_start(hdev, HID_CONNECT_DEFAULT); -+} -+ -+static struct miscdevice acc_device = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = "usb_accessory", -+ .fops = &acc_fops, -+}; -+ -+static const struct hid_device_id acc_hid_table[] = { -+ { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, -+ { } -+}; -+ -+static struct hid_driver acc_hid_driver = { -+ .name = "USB accessory", -+ .id_table = acc_hid_table, -+ .probe = acc_hid_probe, -+}; -+ -+static void acc_complete_setup_noop(struct usb_ep *ep, struct usb_request *req) -+{ -+ /* -+ * Default no-op function when nothing needs to be done for the -+ * setup request -+ */ -+} -+ -+int acc_ctrlrequest(struct usb_composite_dev *cdev, -+ const struct usb_ctrlrequest *ctrl) -+{ -+ struct acc_dev *dev = _acc_dev; -+ int value = -EOPNOTSUPP; -+ struct acc_hid_dev *hid; -+ int offset; -+ u8 b_requestType = ctrl->bRequestType; -+ u8 b_request = ctrl->bRequest; -+ u16 w_index = le16_to_cpu(ctrl->wIndex); -+ u16 w_value = le16_to_cpu(ctrl->wValue); -+ u16 w_length = le16_to_cpu(ctrl->wLength); -+ unsigned long flags; -+ -+/* -+ printk(KERN_INFO "acc_ctrlrequest " -+ "%02x.%02x v%04x i%04x l%u\n", -+ b_requestType, b_request, -+ w_value, w_index, w_length); -+*/ -+ -+ if (b_requestType == (USB_DIR_OUT | USB_TYPE_VENDOR)) { -+ if (b_request == ACCESSORY_START) { -+ dev->start_requested = 1; -+ schedule_delayed_work( -+ &dev->start_work, msecs_to_jiffies(10)); -+ value = 0; -+ cdev->req->complete = acc_complete_setup_noop; -+ } else if (b_request == ACCESSORY_SEND_STRING) { -+ dev->string_index = w_index; -+ cdev->gadget->ep0->driver_data = dev; -+ cdev->req->complete = acc_complete_set_string; -+ value = w_length; -+ } else if (b_request == ACCESSORY_SET_AUDIO_MODE && -+ w_index == 0 && w_length == 0) { -+ dev->audio_mode = w_value; -+ cdev->req->complete = acc_complete_setup_noop; -+ value = 0; -+ } else if (b_request == ACCESSORY_REGISTER_HID) { -+ cdev->req->complete = acc_complete_setup_noop; -+ value = acc_register_hid(dev, w_value, w_index); -+ } else if (b_request == ACCESSORY_UNREGISTER_HID) { -+ cdev->req->complete = acc_complete_setup_noop; -+ value = acc_unregister_hid(dev, w_value); -+ } else if (b_request == ACCESSORY_SET_HID_REPORT_DESC) { -+ spin_lock_irqsave(&dev->lock, flags); -+ hid = acc_hid_get(&dev->new_hid_list, w_value); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ if (!hid) { -+ value = -EINVAL; -+ goto err; -+ } -+ offset = w_index; -+ if (offset != hid->report_desc_offset -+ || offset + w_length > hid->report_desc_len) { -+ value = -EINVAL; -+ goto err; -+ } -+ cdev->req->context = hid; -+ cdev->req->complete = acc_complete_set_hid_report_desc; -+ value = w_length; -+ } else if (b_request == ACCESSORY_SEND_HID_EVENT) { -+ spin_lock_irqsave(&dev->lock, flags); -+ hid = acc_hid_get(&dev->hid_list, w_value); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ if (!hid) { -+ value = -EINVAL; -+ goto err; -+ } -+ cdev->req->context = hid; -+ cdev->req->complete = acc_complete_send_hid_event; -+ value = w_length; -+ } -+ } else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) { -+ if (b_request == ACCESSORY_GET_PROTOCOL) { -+ *((u16 *)cdev->req->buf) = PROTOCOL_VERSION; -+ value = sizeof(u16); -+ cdev->req->complete = acc_complete_setup_noop; -+ /* clear any string left over from a previous session */ -+ memset(dev->manufacturer, 0, sizeof(dev->manufacturer)); -+ memset(dev->model, 0, sizeof(dev->model)); -+ memset(dev->description, 0, sizeof(dev->description)); -+ memset(dev->version, 0, sizeof(dev->version)); -+ memset(dev->uri, 0, sizeof(dev->uri)); -+ memset(dev->serial, 0, sizeof(dev->serial)); -+ dev->start_requested = 0; -+ dev->audio_mode = 0; -+ } -+ } -+ -+ if (value >= 0) { -+ cdev->req->zero = 0; -+ cdev->req->length = value; -+ value = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC); -+ if (value < 0) -+ ERROR(cdev, "%s setup response queue error\n", -+ __func__); -+ } -+ -+err: -+ if (value == -EOPNOTSUPP) -+ VDBG(cdev, -+ "unknown class-specific control req " -+ "%02x.%02x v%04x i%04x l%u\n", -+ ctrl->bRequestType, ctrl->bRequest, -+ w_value, w_index, w_length); -+ return value; -+} -+EXPORT_SYMBOL_GPL(acc_ctrlrequest); -+ -+static int -+__acc_function_bind(struct usb_configuration *c, -+ struct usb_function *f, bool configfs) -+{ -+ struct usb_composite_dev *cdev = c->cdev; -+ struct acc_dev *dev = func_to_dev(f); -+ int id; -+ int ret; -+ -+ DBG(cdev, "acc_function_bind dev: %p\n", dev); -+ -+ if (configfs) { -+ if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) { -+ ret = usb_string_id(c->cdev); -+ if (ret < 0) -+ return ret; -+ acc_string_defs[INTERFACE_STRING_INDEX].id = ret; -+ acc_interface_desc.iInterface = ret; -+ } -+ dev->cdev = c->cdev; -+ } -+ ret = hid_register_driver(&acc_hid_driver); -+ if (ret) -+ return ret; -+ -+ dev->start_requested = 0; -+ -+ /* allocate interface ID(s) */ -+ id = usb_interface_id(c, f); -+ if (id < 0) -+ return id; -+ acc_interface_desc.bInterfaceNumber = id; -+ -+ /* allocate endpoints */ -+ ret = create_bulk_endpoints(dev, &acc_fullspeed_in_desc, -+ &acc_fullspeed_out_desc); -+ if (ret) -+ return ret; -+ -+ /* support high speed hardware */ -+ if (gadget_is_dualspeed(c->cdev->gadget)) { -+ acc_highspeed_in_desc.bEndpointAddress = -+ acc_fullspeed_in_desc.bEndpointAddress; -+ acc_highspeed_out_desc.bEndpointAddress = -+ acc_fullspeed_out_desc.bEndpointAddress; -+ } -+ -+ DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", -+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", -+ f->name, dev->ep_in->name, dev->ep_out->name); -+ return 0; -+} -+ -+static int -+acc_function_bind_configfs(struct usb_configuration *c, -+ struct usb_function *f) { -+ return __acc_function_bind(c, f, true); -+} -+ -+static void -+kill_all_hid_devices(struct acc_dev *dev) -+{ -+ struct acc_hid_dev *hid; -+ struct list_head *entry, *temp; -+ unsigned long flags; -+ -+ /* do nothing if usb accessory device doesn't exist */ -+ if (!dev) -+ return; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ list_for_each_safe(entry, temp, &dev->hid_list) { -+ hid = list_entry(entry, struct acc_hid_dev, list); -+ list_del(&hid->list); -+ list_add(&hid->list, &dev->dead_hid_list); -+ } -+ list_for_each_safe(entry, temp, &dev->new_hid_list) { -+ hid = list_entry(entry, struct acc_hid_dev, list); -+ list_del(&hid->list); -+ list_add(&hid->list, &dev->dead_hid_list); -+ } -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ schedule_work(&dev->hid_work); -+} -+ -+static void -+acc_hid_unbind(struct acc_dev *dev) -+{ -+ hid_unregister_driver(&acc_hid_driver); -+ kill_all_hid_devices(dev); -+} -+ -+static void -+acc_function_unbind(struct usb_configuration *c, struct usb_function *f) -+{ -+ struct acc_dev *dev = func_to_dev(f); -+ struct usb_request *req; -+ int i; -+ -+ dev->online = 0; /* clear online flag */ -+ wake_up(&dev->read_wq); /* unblock reads on closure */ -+ wake_up(&dev->write_wq); /* likewise for writes */ -+ -+ while ((req = req_get(dev, &dev->tx_idle))) -+ acc_request_free(req, dev->ep_in); -+ for (i = 0; i < RX_REQ_MAX; i++) -+ acc_request_free(dev->rx_req[i], dev->ep_out); -+ -+ acc_hid_unbind(dev); -+} -+ -+static void acc_start_work(struct work_struct *data) -+{ -+ char *envp[2] = { "ACCESSORY=START", NULL }; -+ -+ kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp); -+} -+ -+static int acc_hid_init(struct acc_hid_dev *hdev) -+{ -+ struct hid_device *hid; -+ int ret; -+ -+ hid = hid_allocate_device(); -+ if (IS_ERR(hid)) -+ return PTR_ERR(hid); -+ -+ hid->ll_driver = &acc_hid_ll_driver; -+ hid->dev.parent = acc_device.this_device; -+ -+ hid->bus = BUS_USB; -+ hid->vendor = HID_ANY_ID; -+ hid->product = HID_ANY_ID; -+ hid->driver_data = hdev; -+ ret = hid_add_device(hid); -+ if (ret) { -+ pr_err("can't add hid device: %d\n", ret); -+ hid_destroy_device(hid); -+ return ret; -+ } -+ -+ hdev->hid = hid; -+ return 0; -+} -+ -+static void acc_hid_delete(struct acc_hid_dev *hid) -+{ -+ kfree(hid->report_desc); -+ kfree(hid); -+} -+ -+static void acc_hid_work(struct work_struct *data) -+{ -+ struct acc_dev *dev = _acc_dev; -+ struct list_head *entry, *temp; -+ struct acc_hid_dev *hid; -+ struct list_head new_list, dead_list; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD(&new_list); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* copy hids that are ready for initialization to new_list */ -+ list_for_each_safe(entry, temp, &dev->new_hid_list) { -+ hid = list_entry(entry, struct acc_hid_dev, list); -+ if (hid->report_desc_offset == hid->report_desc_len) -+ list_move(&hid->list, &new_list); -+ } -+ -+ if (list_empty(&dev->dead_hid_list)) { -+ INIT_LIST_HEAD(&dead_list); -+ } else { -+ /* move all of dev->dead_hid_list to dead_list */ -+ dead_list.prev = dev->dead_hid_list.prev; -+ dead_list.next = dev->dead_hid_list.next; -+ dead_list.next->prev = &dead_list; -+ dead_list.prev->next = &dead_list; -+ INIT_LIST_HEAD(&dev->dead_hid_list); -+ } -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ /* register new HID devices */ -+ list_for_each_safe(entry, temp, &new_list) { -+ hid = list_entry(entry, struct acc_hid_dev, list); -+ if (acc_hid_init(hid)) { -+ pr_err("can't add HID device %p\n", hid); -+ acc_hid_delete(hid); -+ } else { -+ spin_lock_irqsave(&dev->lock, flags); -+ list_move(&hid->list, &dev->hid_list); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ } -+ } -+ -+ /* remove dead HID devices */ -+ list_for_each_safe(entry, temp, &dead_list) { -+ hid = list_entry(entry, struct acc_hid_dev, list); -+ list_del(&hid->list); -+ if (hid->hid) -+ hid_destroy_device(hid->hid); -+ acc_hid_delete(hid); -+ } -+} -+ -+static int acc_function_set_alt(struct usb_function *f, -+ unsigned intf, unsigned alt) -+{ -+ struct acc_dev *dev = func_to_dev(f); -+ struct usb_composite_dev *cdev = f->config->cdev; -+ int ret; -+ -+ DBG(cdev, "acc_function_set_alt intf: %d alt: %d\n", intf, alt); -+ -+ ret = config_ep_by_speed(cdev->gadget, f, dev->ep_in); -+ if (ret) -+ return ret; -+ -+ ret = usb_ep_enable(dev->ep_in); -+ if (ret) -+ return ret; -+ -+ ret = config_ep_by_speed(cdev->gadget, f, dev->ep_out); -+ if (ret) -+ return ret; -+ -+ ret = usb_ep_enable(dev->ep_out); -+ if (ret) { -+ usb_ep_disable(dev->ep_in); -+ return ret; -+ } -+ -+ dev->online = 1; -+ dev->disconnected = 0; /* if online then not disconnected */ -+ -+ /* readers may be blocked waiting for us to go online */ -+ wake_up(&dev->read_wq); -+ return 0; -+} -+ -+static void acc_function_disable(struct usb_function *f) -+{ -+ struct acc_dev *dev = func_to_dev(f); -+ struct usb_composite_dev *cdev = dev->cdev; -+ -+ DBG(cdev, "acc_function_disable\n"); -+ acc_set_disconnected(dev); /* this now only sets disconnected */ -+ dev->online = 0; /* so now need to clear online flag here too */ -+ usb_ep_disable(dev->ep_in); -+ usb_ep_disable(dev->ep_out); -+ -+ /* readers may be blocked waiting for us to go online */ -+ wake_up(&dev->read_wq); -+ -+ VDBG(cdev, "%s disabled\n", dev->function.name); -+} -+ -+static int acc_setup(void) -+{ -+ struct acc_dev *dev; -+ int ret; -+ -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); -+ if (!dev) -+ return -ENOMEM; -+ -+ spin_lock_init(&dev->lock); -+ init_waitqueue_head(&dev->read_wq); -+ init_waitqueue_head(&dev->write_wq); -+ atomic_set(&dev->open_excl, 0); -+ INIT_LIST_HEAD(&dev->tx_idle); -+ INIT_LIST_HEAD(&dev->hid_list); -+ INIT_LIST_HEAD(&dev->new_hid_list); -+ INIT_LIST_HEAD(&dev->dead_hid_list); -+ INIT_DELAYED_WORK(&dev->start_work, acc_start_work); -+ INIT_WORK(&dev->hid_work, acc_hid_work); -+ -+ /* _acc_dev must be set before calling usb_gadget_register_driver */ -+ _acc_dev = dev; -+ -+ ret = misc_register(&acc_device); -+ if (ret) -+ goto err; -+ -+ return 0; -+ -+err: -+ kfree(dev); -+ pr_err("USB accessory gadget driver failed to initialize\n"); -+ return ret; -+} -+ -+void acc_disconnect(void) -+{ -+ /* unregister all HID devices if USB is disconnected */ -+ kill_all_hid_devices(_acc_dev); -+} -+EXPORT_SYMBOL_GPL(acc_disconnect); -+ -+static void acc_cleanup(void) -+{ -+ misc_deregister(&acc_device); -+ kfree(_acc_dev); -+ _acc_dev = NULL; -+} -+static struct acc_instance *to_acc_instance(struct config_item *item) -+{ -+ return container_of(to_config_group(item), struct acc_instance, -+ func_inst.group); -+} -+ -+static void acc_attr_release(struct config_item *item) -+{ -+ struct acc_instance *fi_acc = to_acc_instance(item); -+ -+ usb_put_function_instance(&fi_acc->func_inst); -+} -+ -+static struct configfs_item_operations acc_item_ops = { -+ .release = acc_attr_release, -+}; -+ -+static struct config_item_type acc_func_type = { -+ .ct_item_ops = &acc_item_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct acc_instance *to_fi_acc(struct usb_function_instance *fi) -+{ -+ return container_of(fi, struct acc_instance, func_inst); -+} -+ -+static int acc_set_inst_name(struct usb_function_instance *fi, const char *name) -+{ -+ struct acc_instance *fi_acc; -+ char *ptr; -+ int name_len; -+ -+ name_len = strlen(name) + 1; -+ if (name_len > MAX_INST_NAME_LEN) -+ return -ENAMETOOLONG; -+ -+ ptr = kstrndup(name, name_len, GFP_KERNEL); -+ if (!ptr) -+ return -ENOMEM; -+ -+ fi_acc = to_fi_acc(fi); -+ fi_acc->name = ptr; -+ return 0; -+} -+ -+static void acc_free_inst(struct usb_function_instance *fi) -+{ -+ struct acc_instance *fi_acc; -+ -+ fi_acc = to_fi_acc(fi); -+ kfree(fi_acc->name); -+ acc_cleanup(); -+} -+ -+static struct usb_function_instance *acc_alloc_inst(void) -+{ -+ struct acc_instance *fi_acc; -+ struct acc_dev *dev; -+ int err; -+ -+ fi_acc = kzalloc(sizeof(*fi_acc), GFP_KERNEL); -+ if (!fi_acc) -+ return ERR_PTR(-ENOMEM); -+ fi_acc->func_inst.set_inst_name = acc_set_inst_name; -+ fi_acc->func_inst.free_func_inst = acc_free_inst; -+ -+ err = acc_setup(); -+ if (err) { -+ kfree(fi_acc); -+ pr_err("Error setting ACCESSORY\n"); -+ return ERR_PTR(err); -+ } -+ -+ config_group_init_type_name(&fi_acc->func_inst.group, -+ "", &acc_func_type); -+ dev = _acc_dev; -+ return &fi_acc->func_inst; -+} -+ -+static void acc_free(struct usb_function *f) -+{ -+/*NO-OP: no function specific resource allocation in mtp_alloc*/ -+} -+ -+int acc_ctrlrequest_configfs(struct usb_function *f, -+ const struct usb_ctrlrequest *ctrl) { -+ if (f->config != NULL && f->config->cdev != NULL) -+ return acc_ctrlrequest(f->config->cdev, ctrl); -+ else -+ return -1; -+} -+ -+static struct usb_function *acc_alloc(struct usb_function_instance *fi) -+{ -+ struct acc_dev *dev = _acc_dev; -+ -+ pr_info("acc_alloc\n"); -+ -+ dev->function.name = "accessory"; -+ dev->function.strings = acc_strings, -+ dev->function.fs_descriptors = fs_acc_descs; -+ dev->function.hs_descriptors = hs_acc_descs; -+ dev->function.bind = acc_function_bind_configfs; -+ dev->function.unbind = acc_function_unbind; -+ dev->function.set_alt = acc_function_set_alt; -+ dev->function.disable = acc_function_disable; -+ dev->function.free_func = acc_free; -+ dev->function.setup = acc_ctrlrequest_configfs; -+ -+ return &dev->function; -+} -+DECLARE_USB_FUNCTION_INIT(accessory, acc_alloc_inst, acc_alloc); -+MODULE_LICENSE("GPL"); -diff --git a/include/linux/usb/f_accessory.h b/include/linux/usb/f_accessory.h -new file mode 100644 -index 000000000000..ebe3c4d59309 ---- /dev/null -+++ b/include/linux/usb/f_accessory.h -@@ -0,0 +1,23 @@ -+/* -+ * Gadget Function Driver for Android USB accessories -+ * -+ * Copyright (C) 2011 Google, Inc. -+ * Author: Mike Lockwood -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+#ifndef __LINUX_USB_F_ACCESSORY_H -+#define __LINUX_USB_F_ACCESSORY_H -+ -+#include -+ -+#endif /* __LINUX_USB_F_ACCESSORY_H */ -diff --git a/include/uapi/linux/usb/f_accessory.h b/include/uapi/linux/usb/f_accessory.h -new file mode 100644 -index 000000000000..0baeb7d0d74c ---- /dev/null -+++ b/include/uapi/linux/usb/f_accessory.h -@@ -0,0 +1,146 @@ -+/* -+ * Gadget Function Driver for Android USB accessories -+ * -+ * Copyright (C) 2011 Google, Inc. -+ * Author: Mike Lockwood -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+#ifndef _UAPI_LINUX_USB_F_ACCESSORY_H -+#define _UAPI_LINUX_USB_F_ACCESSORY_H -+ -+/* Use Google Vendor ID when in accessory mode */ -+#define USB_ACCESSORY_VENDOR_ID 0x18D1 -+ -+ -+/* Product ID to use when in accessory mode */ -+#define USB_ACCESSORY_PRODUCT_ID 0x2D00 -+ -+/* Product ID to use when in accessory mode and adb is enabled */ -+#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01 -+ -+/* Indexes for strings sent by the host via ACCESSORY_SEND_STRING */ -+#define ACCESSORY_STRING_MANUFACTURER 0 -+#define ACCESSORY_STRING_MODEL 1 -+#define ACCESSORY_STRING_DESCRIPTION 2 -+#define ACCESSORY_STRING_VERSION 3 -+#define ACCESSORY_STRING_URI 4 -+#define ACCESSORY_STRING_SERIAL 5 -+ -+/* Control request for retrieving device's protocol version -+ * -+ * requestType: USB_DIR_IN | USB_TYPE_VENDOR -+ * request: ACCESSORY_GET_PROTOCOL -+ * value: 0 -+ * index: 0 -+ * data version number (16 bits little endian) -+ * 1 for original accessory support -+ * 2 adds HID and device to host audio support -+ */ -+#define ACCESSORY_GET_PROTOCOL 51 -+ -+/* Control request for host to send a string to the device -+ * -+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR -+ * request: ACCESSORY_SEND_STRING -+ * value: 0 -+ * index: string ID -+ * data zero terminated UTF8 string -+ * -+ * The device can later retrieve these strings via the -+ * ACCESSORY_GET_STRING_* ioctls -+ */ -+#define ACCESSORY_SEND_STRING 52 -+ -+/* Control request for starting device in accessory mode. -+ * The host sends this after setting all its strings to the device. -+ * -+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR -+ * request: ACCESSORY_START -+ * value: 0 -+ * index: 0 -+ * data none -+ */ -+#define ACCESSORY_START 53 -+ -+/* Control request for registering a HID device. -+ * Upon registering, a unique ID is sent by the accessory in the -+ * value parameter. This ID will be used for future commands for -+ * the device -+ * -+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR -+ * request: ACCESSORY_REGISTER_HID_DEVICE -+ * value: Accessory assigned ID for the HID device -+ * index: total length of the HID report descriptor -+ * data none -+ */ -+#define ACCESSORY_REGISTER_HID 54 -+ -+/* Control request for unregistering a HID device. -+ * -+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR -+ * request: ACCESSORY_REGISTER_HID -+ * value: Accessory assigned ID for the HID device -+ * index: 0 -+ * data none -+ */ -+#define ACCESSORY_UNREGISTER_HID 55 -+ -+/* Control request for sending the HID report descriptor. -+ * If the HID descriptor is longer than the endpoint zero max packet size, -+ * the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC -+ * commands. The data for the descriptor must be sent sequentially -+ * if multiple packets are needed. -+ * -+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR -+ * request: ACCESSORY_SET_HID_REPORT_DESC -+ * value: Accessory assigned ID for the HID device -+ * index: offset of data in descriptor -+ * (needed when HID descriptor is too big for one packet) -+ * data the HID report descriptor -+ */ -+#define ACCESSORY_SET_HID_REPORT_DESC 56 -+ -+/* Control request for sending HID events. -+ * -+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR -+ * request: ACCESSORY_SEND_HID_EVENT -+ * value: Accessory assigned ID for the HID device -+ * index: 0 -+ * data the HID report for the event -+ */ -+#define ACCESSORY_SEND_HID_EVENT 57 -+ -+/* Control request for setting the audio mode. -+ * -+ * requestType: USB_DIR_OUT | USB_TYPE_VENDOR -+ * request: ACCESSORY_SET_AUDIO_MODE -+ * value: 0 - no audio -+ * 1 - device to host, 44100 16-bit stereo PCM -+ * index: 0 -+ * data none -+ */ -+#define ACCESSORY_SET_AUDIO_MODE 58 -+ -+/* ioctls for retrieving strings set by the host */ -+#define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256]) -+#define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256]) -+#define ACCESSORY_GET_STRING_DESCRIPTION _IOW('M', 3, char[256]) -+#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256]) -+#define ACCESSORY_GET_STRING_URI _IOW('M', 5, char[256]) -+#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256]) -+/* returns 1 if there is a start request pending */ -+#define ACCESSORY_IS_START_REQUESTED _IO('M', 7) -+/* returns audio mode (set via the ACCESSORY_SET_AUDIO_MODE control request) */ -+#define ACCESSORY_GET_AUDIO_MODE _IO('M', 8) -+ -+#endif /* _UAPI_LINUX_USB_F_ACCESSORY_H */ diff --git a/patches/ANDROID-usb-gadget-f_audio_source-New-gadget-driver-for-audio-output.patch b/patches/ANDROID-usb-gadget-f_audio_source-New-gadget-driver-for-audio-output.patch deleted file mode 100644 index 40db7bb9e64e4e144ab8e32d81b877101d59e1d1..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-f_audio_source-New-gadget-driver-for-audio-output.patch +++ /dev/null @@ -1,1150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mike Lockwood -Date: Fri, 11 May 2012 09:01:08 -0700 -Subject: ANDROID: usb: gadget: f_audio_source: New gadget driver for audio - output - -This driver presents a standard USB audio class interface to the host -and an ALSA PCM device to userspace - -Bug: 78114713 -Bug: 120441124 -[badhri: f_audio_source is being migrated to userspace.] -Change-Id: If16b14a5ff27045f9cb2daaf1ae9195c5eeab7d0 -Signed-off-by: Mike Lockwood -[AmitP: Folded following android-4.9 commit changes into this patch - Parts of e27543931009 ("ANDROID: usb: gadget: Fixes and hacks to make android usb gadget compile on 3.8") - i6d9285e2574a ("ANDROID: usb: gadget: f_audio_source:replace deprecated API")] -Signed-off-by: Amit Pundir -[astrachan: Folded the following changes into this patch: - ddfd0c4070c1 ("ANDROID: usb: gadget: f_audio_source: Move to USB_FUNCTION API") - a3ab81aaa19e ("ANDROID: usb: gadget: f_audio_source: Move gadget functions code") - 2095c953d894 ("ANDROID: usb: gadget: f_audio_source: change max ISO packet size") - 8671b3e53638 ("ANDROID: usb: gadget: f_audio_source: Fixed USB Audio Class Interface Descriptor") - af98f36edbe2 ("ANDROID: usb: gadget: f_audio_source: disable the CPU C-states upon playback") - a830751a338e ("CHROMIUM: usb: gadget: f_audio_source: add .free_func callback")] -Signed-off-by: Alistair Strachan ---- - drivers/usb/gadget/Kconfig | 12 + - drivers/usb/gadget/function/Makefile | 2 + - drivers/usb/gadget/function/f_audio_source.c | 1071 ++++++++++++++++++ - 3 files changed, 1085 insertions(+) - create mode 100644 drivers/usb/gadget/function/f_audio_source.c - -diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig -index 7749fb1decb0..920ff2d2c557 100644 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -219,6 +219,9 @@ config USB_F_TCM - config USB_F_ACC - tristate - -+config USB_F_AUDIO_SRC -+ tristate -+ - # this first set of drivers all depend on bulk-capable hardware. - - config USB_CONFIGFS -@@ -387,6 +390,15 @@ config USB_CONFIGFS_F_ACC - help - USB gadget Accessory support - -+config USB_CONFIGFS_F_AUDIO_SRC -+ bool "Audio Source gadget" -+ depends on USB_CONFIGFS -+ depends on SND -+ select SND_PCM -+ select USB_F_AUDIO_SRC -+ help -+ USB gadget Audio Source support -+ - config USB_CONFIGFS_F_UAC1 - bool "Audio Class 1.0" - depends on USB_CONFIGFS -diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile -index 2305360e5f22..dd33a1243342 100644 ---- a/drivers/usb/gadget/function/Makefile -+++ b/drivers/usb/gadget/function/Makefile -@@ -52,3 +52,5 @@ usb_f_tcm-y := f_tcm.o - obj-$(CONFIG_USB_F_TCM) += usb_f_tcm.o - usb_f_accessory-y := f_accessory.o - obj-$(CONFIG_USB_F_ACC) += usb_f_accessory.o -+usb_f_audio_source-y := f_audio_source.o -+obj-$(CONFIG_USB_F_AUDIO_SRC) += usb_f_audio_source.o -diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c -new file mode 100644 -index 000000000000..8124af33b738 ---- /dev/null -+++ b/drivers/usb/gadget/function/f_audio_source.c -@@ -0,0 +1,1071 @@ -+/* -+ * Gadget Function Driver for USB audio source device -+ * -+ * Copyright (C) 2012 Google, Inc. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * 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. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#define SAMPLE_RATE 44100 -+#define FRAMES_PER_MSEC (SAMPLE_RATE / 1000) -+ -+#define IN_EP_MAX_PACKET_SIZE 256 -+ -+/* Number of requests to allocate */ -+#define IN_EP_REQ_COUNT 4 -+ -+#define AUDIO_AC_INTERFACE 0 -+#define AUDIO_AS_INTERFACE 1 -+#define AUDIO_NUM_INTERFACES 2 -+#define MAX_INST_NAME_LEN 40 -+ -+/* B.3.1 Standard AC Interface Descriptor */ -+static struct usb_interface_descriptor ac_interface_desc = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bNumEndpoints = 0, -+ .bInterfaceClass = USB_CLASS_AUDIO, -+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, -+}; -+ -+DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); -+ -+#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(AUDIO_NUM_INTERFACES) -+/* 1 input terminal, 1 output terminal and 1 feature unit */ -+#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \ -+ + UAC_DT_INPUT_TERMINAL_SIZE + UAC_DT_OUTPUT_TERMINAL_SIZE \ -+ + UAC_DT_FEATURE_UNIT_SIZE(0)) -+/* B.3.2 Class-Specific AC Interface Descriptor */ -+static struct uac1_ac_header_descriptor_2 ac_header_desc = { -+ .bLength = UAC_DT_AC_HEADER_LENGTH, -+ .bDescriptorType = USB_DT_CS_INTERFACE, -+ .bDescriptorSubtype = UAC_HEADER, -+ .bcdADC = __constant_cpu_to_le16(0x0100), -+ .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH), -+ .bInCollection = AUDIO_NUM_INTERFACES, -+ .baInterfaceNr = { -+ [0] = AUDIO_AC_INTERFACE, -+ [1] = AUDIO_AS_INTERFACE, -+ } -+}; -+ -+#define INPUT_TERMINAL_ID 1 -+static struct uac_input_terminal_descriptor input_terminal_desc = { -+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE, -+ .bDescriptorType = USB_DT_CS_INTERFACE, -+ .bDescriptorSubtype = UAC_INPUT_TERMINAL, -+ .bTerminalID = INPUT_TERMINAL_ID, -+ .wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE, -+ .bAssocTerminal = 0, -+ .wChannelConfig = 0x3, -+}; -+ -+DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0); -+ -+#define FEATURE_UNIT_ID 2 -+static struct uac_feature_unit_descriptor_0 feature_unit_desc = { -+ .bLength = UAC_DT_FEATURE_UNIT_SIZE(0), -+ .bDescriptorType = USB_DT_CS_INTERFACE, -+ .bDescriptorSubtype = UAC_FEATURE_UNIT, -+ .bUnitID = FEATURE_UNIT_ID, -+ .bSourceID = INPUT_TERMINAL_ID, -+ .bControlSize = 2, -+}; -+ -+#define OUTPUT_TERMINAL_ID 3 -+static struct uac1_output_terminal_descriptor output_terminal_desc = { -+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, -+ .bDescriptorType = USB_DT_CS_INTERFACE, -+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, -+ .bTerminalID = OUTPUT_TERMINAL_ID, -+ .wTerminalType = UAC_TERMINAL_STREAMING, -+ .bAssocTerminal = FEATURE_UNIT_ID, -+ .bSourceID = FEATURE_UNIT_ID, -+}; -+ -+/* B.4.1 Standard AS Interface Descriptor */ -+static struct usb_interface_descriptor as_interface_alt_0_desc = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bAlternateSetting = 0, -+ .bNumEndpoints = 0, -+ .bInterfaceClass = USB_CLASS_AUDIO, -+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, -+}; -+ -+static struct usb_interface_descriptor as_interface_alt_1_desc = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bAlternateSetting = 1, -+ .bNumEndpoints = 1, -+ .bInterfaceClass = USB_CLASS_AUDIO, -+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, -+}; -+ -+/* B.4.2 Class-Specific AS Interface Descriptor */ -+static struct uac1_as_header_descriptor as_header_desc = { -+ .bLength = UAC_DT_AS_HEADER_SIZE, -+ .bDescriptorType = USB_DT_CS_INTERFACE, -+ .bDescriptorSubtype = UAC_AS_GENERAL, -+ .bTerminalLink = INPUT_TERMINAL_ID, -+ .bDelay = 1, -+ .wFormatTag = UAC_FORMAT_TYPE_I_PCM, -+}; -+ -+DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1); -+ -+static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = { -+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), -+ .bDescriptorType = USB_DT_CS_INTERFACE, -+ .bDescriptorSubtype = UAC_FORMAT_TYPE, -+ .bFormatType = UAC_FORMAT_TYPE_I, -+ .bSubframeSize = 2, -+ .bBitResolution = 16, -+ .bSamFreqType = 1, -+}; -+ -+/* Standard ISO IN Endpoint Descriptor for highspeed */ -+static struct usb_endpoint_descriptor hs_as_in_ep_desc = { -+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = USB_DIR_IN, -+ .bmAttributes = USB_ENDPOINT_SYNC_SYNC -+ | USB_ENDPOINT_XFER_ISOC, -+ .wMaxPacketSize = __constant_cpu_to_le16(IN_EP_MAX_PACKET_SIZE), -+ .bInterval = 4, /* poll 1 per millisecond */ -+}; -+ -+/* Standard ISO IN Endpoint Descriptor for highspeed */ -+static struct usb_endpoint_descriptor fs_as_in_ep_desc = { -+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = USB_DIR_IN, -+ .bmAttributes = USB_ENDPOINT_SYNC_SYNC -+ | USB_ENDPOINT_XFER_ISOC, -+ .wMaxPacketSize = __constant_cpu_to_le16(IN_EP_MAX_PACKET_SIZE), -+ .bInterval = 1, /* poll 1 per millisecond */ -+}; -+ -+/* Class-specific AS ISO OUT Endpoint Descriptor */ -+static struct uac_iso_endpoint_descriptor as_iso_in_desc = { -+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, -+ .bDescriptorType = USB_DT_CS_ENDPOINT, -+ .bDescriptorSubtype = UAC_EP_GENERAL, -+ .bmAttributes = 1, -+ .bLockDelayUnits = 1, -+ .wLockDelay = __constant_cpu_to_le16(1), -+}; -+ -+static struct usb_descriptor_header *hs_audio_desc[] = { -+ (struct usb_descriptor_header *)&ac_interface_desc, -+ (struct usb_descriptor_header *)&ac_header_desc, -+ -+ (struct usb_descriptor_header *)&input_terminal_desc, -+ (struct usb_descriptor_header *)&output_terminal_desc, -+ (struct usb_descriptor_header *)&feature_unit_desc, -+ -+ (struct usb_descriptor_header *)&as_interface_alt_0_desc, -+ (struct usb_descriptor_header *)&as_interface_alt_1_desc, -+ (struct usb_descriptor_header *)&as_header_desc, -+ -+ (struct usb_descriptor_header *)&as_type_i_desc, -+ -+ (struct usb_descriptor_header *)&hs_as_in_ep_desc, -+ (struct usb_descriptor_header *)&as_iso_in_desc, -+ NULL, -+}; -+ -+static struct usb_descriptor_header *fs_audio_desc[] = { -+ (struct usb_descriptor_header *)&ac_interface_desc, -+ (struct usb_descriptor_header *)&ac_header_desc, -+ -+ (struct usb_descriptor_header *)&input_terminal_desc, -+ (struct usb_descriptor_header *)&output_terminal_desc, -+ (struct usb_descriptor_header *)&feature_unit_desc, -+ -+ (struct usb_descriptor_header *)&as_interface_alt_0_desc, -+ (struct usb_descriptor_header *)&as_interface_alt_1_desc, -+ (struct usb_descriptor_header *)&as_header_desc, -+ -+ (struct usb_descriptor_header *)&as_type_i_desc, -+ -+ (struct usb_descriptor_header *)&fs_as_in_ep_desc, -+ (struct usb_descriptor_header *)&as_iso_in_desc, -+ NULL, -+}; -+ -+static struct snd_pcm_hardware audio_hw_info = { -+ .info = SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_MMAP_VALID | -+ SNDRV_PCM_INFO_BATCH | -+ SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_BLOCK_TRANSFER, -+ -+ .formats = SNDRV_PCM_FMTBIT_S16_LE, -+ .channels_min = 2, -+ .channels_max = 2, -+ .rate_min = SAMPLE_RATE, -+ .rate_max = SAMPLE_RATE, -+ -+ .buffer_bytes_max = 1024 * 1024, -+ .period_bytes_min = 64, -+ .period_bytes_max = 512 * 1024, -+ .periods_min = 2, -+ .periods_max = 1024, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+struct audio_source_config { -+ int card; -+ int device; -+}; -+ -+struct audio_dev { -+ struct usb_function func; -+ struct snd_card *card; -+ struct snd_pcm *pcm; -+ struct snd_pcm_substream *substream; -+ -+ struct list_head idle_reqs; -+ struct usb_ep *in_ep; -+ -+ spinlock_t lock; -+ -+ /* beginning, end and current position in our buffer */ -+ void *buffer_start; -+ void *buffer_end; -+ void *buffer_pos; -+ -+ /* byte size of a "period" */ -+ unsigned int period; -+ /* bytes sent since last call to snd_pcm_period_elapsed */ -+ unsigned int period_offset; -+ /* time we started playing */ -+ ktime_t start_time; -+ /* number of frames sent since start_time */ -+ s64 frames_sent; -+ struct audio_source_config *config; -+ /* for creating and issuing QoS requests */ -+ struct pm_qos_request pm_qos; -+}; -+ -+static inline struct audio_dev *func_to_audio(struct usb_function *f) -+{ -+ return container_of(f, struct audio_dev, func); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+struct audio_source_instance { -+ struct usb_function_instance func_inst; -+ const char *name; -+ struct audio_source_config *config; -+ struct device *audio_device; -+}; -+ -+static void audio_source_attr_release(struct config_item *item); -+ -+static struct configfs_item_operations audio_source_item_ops = { -+ .release = audio_source_attr_release, -+}; -+ -+static struct config_item_type audio_source_func_type = { -+ .ct_item_ops = &audio_source_item_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static ssize_t audio_source_pcm_show(struct device *dev, -+ struct device_attribute *attr, char *buf); -+ -+static DEVICE_ATTR(pcm, S_IRUGO, audio_source_pcm_show, NULL); -+ -+static struct device_attribute *audio_source_function_attributes[] = { -+ &dev_attr_pcm, -+ NULL -+}; -+ -+/*--------------------------------------------------------------------------*/ -+ -+static struct usb_request *audio_request_new(struct usb_ep *ep, int buffer_size) -+{ -+ struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); -+ -+ if (!req) -+ return NULL; -+ -+ req->buf = kmalloc(buffer_size, GFP_KERNEL); -+ if (!req->buf) { -+ usb_ep_free_request(ep, req); -+ return NULL; -+ } -+ req->length = buffer_size; -+ return req; -+} -+ -+static void audio_request_free(struct usb_request *req, struct usb_ep *ep) -+{ -+ if (req) { -+ kfree(req->buf); -+ usb_ep_free_request(ep, req); -+ } -+} -+ -+static void audio_req_put(struct audio_dev *audio, struct usb_request *req) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&audio->lock, flags); -+ list_add_tail(&req->list, &audio->idle_reqs); -+ spin_unlock_irqrestore(&audio->lock, flags); -+} -+ -+static struct usb_request *audio_req_get(struct audio_dev *audio) -+{ -+ unsigned long flags; -+ struct usb_request *req; -+ -+ spin_lock_irqsave(&audio->lock, flags); -+ if (list_empty(&audio->idle_reqs)) { -+ req = 0; -+ } else { -+ req = list_first_entry(&audio->idle_reqs, struct usb_request, -+ list); -+ list_del(&req->list); -+ } -+ spin_unlock_irqrestore(&audio->lock, flags); -+ return req; -+} -+ -+/* send the appropriate number of packets to match our bitrate */ -+static void audio_send(struct audio_dev *audio) -+{ -+ struct snd_pcm_runtime *runtime; -+ struct usb_request *req; -+ int length, length1, length2, ret; -+ s64 msecs; -+ s64 frames; -+ ktime_t now; -+ -+ /* audio->substream will be null if we have been closed */ -+ if (!audio->substream) -+ return; -+ /* audio->buffer_pos will be null if we have been stopped */ -+ if (!audio->buffer_pos) -+ return; -+ -+ runtime = audio->substream->runtime; -+ -+ /* compute number of frames to send */ -+ now = ktime_get(); -+ msecs = div_s64((ktime_to_ns(now) - ktime_to_ns(audio->start_time)), -+ 1000000); -+ frames = div_s64((msecs * SAMPLE_RATE), 1000); -+ -+ /* Readjust our frames_sent if we fall too far behind. -+ * If we get too far behind it is better to drop some frames than -+ * to keep sending data too fast in an attempt to catch up. -+ */ -+ if (frames - audio->frames_sent > 10 * FRAMES_PER_MSEC) -+ audio->frames_sent = frames - FRAMES_PER_MSEC; -+ -+ frames -= audio->frames_sent; -+ -+ /* We need to send something to keep the pipeline going */ -+ if (frames <= 0) -+ frames = FRAMES_PER_MSEC; -+ -+ while (frames > 0) { -+ req = audio_req_get(audio); -+ if (!req) -+ break; -+ -+ length = frames_to_bytes(runtime, frames); -+ if (length > IN_EP_MAX_PACKET_SIZE) -+ length = IN_EP_MAX_PACKET_SIZE; -+ -+ if (audio->buffer_pos + length > audio->buffer_end) -+ length1 = audio->buffer_end - audio->buffer_pos; -+ else -+ length1 = length; -+ memcpy(req->buf, audio->buffer_pos, length1); -+ if (length1 < length) { -+ /* Wrap around and copy remaining length -+ * at beginning of buffer. -+ */ -+ length2 = length - length1; -+ memcpy(req->buf + length1, audio->buffer_start, -+ length2); -+ audio->buffer_pos = audio->buffer_start + length2; -+ } else { -+ audio->buffer_pos += length1; -+ if (audio->buffer_pos >= audio->buffer_end) -+ audio->buffer_pos = audio->buffer_start; -+ } -+ -+ req->length = length; -+ ret = usb_ep_queue(audio->in_ep, req, GFP_ATOMIC); -+ if (ret < 0) { -+ pr_err("usb_ep_queue failed ret: %d\n", ret); -+ audio_req_put(audio, req); -+ break; -+ } -+ -+ frames -= bytes_to_frames(runtime, length); -+ audio->frames_sent += bytes_to_frames(runtime, length); -+ } -+} -+ -+static void audio_control_complete(struct usb_ep *ep, struct usb_request *req) -+{ -+ /* nothing to do here */ -+} -+ -+static void audio_data_complete(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct audio_dev *audio = req->context; -+ -+ pr_debug("audio_data_complete req->status %d req->actual %d\n", -+ req->status, req->actual); -+ -+ audio_req_put(audio, req); -+ -+ if (!audio->buffer_start || req->status) -+ return; -+ -+ audio->period_offset += req->actual; -+ if (audio->period_offset >= audio->period) { -+ snd_pcm_period_elapsed(audio->substream); -+ audio->period_offset = 0; -+ } -+ audio_send(audio); -+} -+ -+static int audio_set_endpoint_req(struct usb_function *f, -+ const struct usb_ctrlrequest *ctrl) -+{ -+ int value = -EOPNOTSUPP; -+ u16 ep = le16_to_cpu(ctrl->wIndex); -+ u16 len = le16_to_cpu(ctrl->wLength); -+ u16 w_value = le16_to_cpu(ctrl->wValue); -+ -+ pr_debug("bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", -+ ctrl->bRequest, w_value, len, ep); -+ -+ switch (ctrl->bRequest) { -+ case UAC_SET_CUR: -+ case UAC_SET_MIN: -+ case UAC_SET_MAX: -+ case UAC_SET_RES: -+ value = len; -+ break; -+ default: -+ break; -+ } -+ -+ return value; -+} -+ -+static int audio_get_endpoint_req(struct usb_function *f, -+ const struct usb_ctrlrequest *ctrl) -+{ -+ struct usb_composite_dev *cdev = f->config->cdev; -+ int value = -EOPNOTSUPP; -+ u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); -+ u16 len = le16_to_cpu(ctrl->wLength); -+ u16 w_value = le16_to_cpu(ctrl->wValue); -+ u8 *buf = cdev->req->buf; -+ -+ pr_debug("bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", -+ ctrl->bRequest, w_value, len, ep); -+ -+ if (w_value == UAC_EP_CS_ATTR_SAMPLE_RATE << 8) { -+ switch (ctrl->bRequest) { -+ case UAC_GET_CUR: -+ case UAC_GET_MIN: -+ case UAC_GET_MAX: -+ case UAC_GET_RES: -+ /* return our sample rate */ -+ buf[0] = (u8)SAMPLE_RATE; -+ buf[1] = (u8)(SAMPLE_RATE >> 8); -+ buf[2] = (u8)(SAMPLE_RATE >> 16); -+ value = 3; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return value; -+} -+ -+static int -+audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) -+{ -+ struct usb_composite_dev *cdev = f->config->cdev; -+ struct usb_request *req = cdev->req; -+ int value = -EOPNOTSUPP; -+ u16 w_index = le16_to_cpu(ctrl->wIndex); -+ u16 w_value = le16_to_cpu(ctrl->wValue); -+ u16 w_length = le16_to_cpu(ctrl->wLength); -+ -+ /* composite driver infrastructure handles everything; interface -+ * activation uses set_alt(). -+ */ -+ switch (ctrl->bRequestType) { -+ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: -+ value = audio_set_endpoint_req(f, ctrl); -+ break; -+ -+ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: -+ value = audio_get_endpoint_req(f, ctrl); -+ break; -+ } -+ -+ /* respond with data transfer or status phase? */ -+ if (value >= 0) { -+ pr_debug("audio req%02x.%02x v%04x i%04x l%d\n", -+ ctrl->bRequestType, ctrl->bRequest, -+ w_value, w_index, w_length); -+ req->zero = 0; -+ req->length = value; -+ req->complete = audio_control_complete; -+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); -+ if (value < 0) -+ pr_err("audio response on err %d\n", value); -+ } -+ -+ /* device either stalls (value < 0) or reports success */ -+ return value; -+} -+ -+static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) -+{ -+ struct audio_dev *audio = func_to_audio(f); -+ struct usb_composite_dev *cdev = f->config->cdev; -+ int ret; -+ -+ pr_debug("audio_set_alt intf %d, alt %d\n", intf, alt); -+ -+ ret = config_ep_by_speed(cdev->gadget, f, audio->in_ep); -+ if (ret) -+ return ret; -+ -+ usb_ep_enable(audio->in_ep); -+ return 0; -+} -+ -+static void audio_disable(struct usb_function *f) -+{ -+ struct audio_dev *audio = func_to_audio(f); -+ -+ pr_debug("audio_disable\n"); -+ usb_ep_disable(audio->in_ep); -+} -+ -+static void audio_free_func(struct usb_function *f) -+{ -+ /* no-op */ -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void audio_build_desc(struct audio_dev *audio) -+{ -+ u8 *sam_freq; -+ int rate; -+ -+ /* Set channel numbers */ -+ input_terminal_desc.bNrChannels = 2; -+ as_type_i_desc.bNrChannels = 2; -+ -+ /* Set sample rates */ -+ rate = SAMPLE_RATE; -+ sam_freq = as_type_i_desc.tSamFreq[0]; -+ memcpy(sam_freq, &rate, 3); -+} -+ -+ -+static int snd_card_setup(struct usb_configuration *c, -+ struct audio_source_config *config); -+static struct audio_source_instance *to_fi_audio_source( -+ const struct usb_function_instance *fi); -+ -+ -+/* audio function driver setup/binding */ -+static int -+audio_bind(struct usb_configuration *c, struct usb_function *f) -+{ -+ struct usb_composite_dev *cdev = c->cdev; -+ struct audio_dev *audio = func_to_audio(f); -+ int status; -+ struct usb_ep *ep; -+ struct usb_request *req; -+ int i; -+ int err; -+ -+ if (IS_ENABLED(CONFIG_USB_CONFIGFS)) { -+ struct audio_source_instance *fi_audio = -+ to_fi_audio_source(f->fi); -+ struct audio_source_config *config = -+ fi_audio->config; -+ -+ err = snd_card_setup(c, config); -+ if (err) -+ return err; -+ } -+ -+ audio_build_desc(audio); -+ -+ /* allocate instance-specific interface IDs, and patch descriptors */ -+ status = usb_interface_id(c, f); -+ if (status < 0) -+ goto fail; -+ ac_interface_desc.bInterfaceNumber = status; -+ -+ /* AUDIO_AC_INTERFACE */ -+ ac_header_desc.baInterfaceNr[0] = status; -+ -+ status = usb_interface_id(c, f); -+ if (status < 0) -+ goto fail; -+ as_interface_alt_0_desc.bInterfaceNumber = status; -+ as_interface_alt_1_desc.bInterfaceNumber = status; -+ -+ /* AUDIO_AS_INTERFACE */ -+ ac_header_desc.baInterfaceNr[1] = status; -+ -+ status = -ENODEV; -+ -+ /* allocate our endpoint */ -+ ep = usb_ep_autoconfig(cdev->gadget, &fs_as_in_ep_desc); -+ if (!ep) -+ goto fail; -+ audio->in_ep = ep; -+ ep->driver_data = audio; /* claim */ -+ -+ if (gadget_is_dualspeed(c->cdev->gadget)) -+ hs_as_in_ep_desc.bEndpointAddress = -+ fs_as_in_ep_desc.bEndpointAddress; -+ -+ f->fs_descriptors = fs_audio_desc; -+ f->hs_descriptors = hs_audio_desc; -+ -+ for (i = 0, status = 0; i < IN_EP_REQ_COUNT && status == 0; i++) { -+ req = audio_request_new(ep, IN_EP_MAX_PACKET_SIZE); -+ if (req) { -+ req->context = audio; -+ req->complete = audio_data_complete; -+ audio_req_put(audio, req); -+ } else -+ status = -ENOMEM; -+ } -+ -+fail: -+ return status; -+} -+ -+static void -+audio_unbind(struct usb_configuration *c, struct usb_function *f) -+{ -+ struct audio_dev *audio = func_to_audio(f); -+ struct usb_request *req; -+ -+ while ((req = audio_req_get(audio))) -+ audio_request_free(req, audio->in_ep); -+ -+ snd_card_free_when_closed(audio->card); -+ audio->card = NULL; -+ audio->pcm = NULL; -+ audio->substream = NULL; -+ audio->in_ep = NULL; -+ -+ if (IS_ENABLED(CONFIG_USB_CONFIGFS)) { -+ struct audio_source_instance *fi_audio = -+ to_fi_audio_source(f->fi); -+ struct audio_source_config *config = -+ fi_audio->config; -+ -+ config->card = -1; -+ config->device = -1; -+ } -+} -+ -+static void audio_pcm_playback_start(struct audio_dev *audio) -+{ -+ audio->start_time = ktime_get(); -+ audio->frames_sent = 0; -+ audio_send(audio); -+} -+ -+static void audio_pcm_playback_stop(struct audio_dev *audio) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&audio->lock, flags); -+ audio->buffer_start = 0; -+ audio->buffer_end = 0; -+ audio->buffer_pos = 0; -+ spin_unlock_irqrestore(&audio->lock, flags); -+} -+ -+static int audio_pcm_open(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct audio_dev *audio = substream->private_data; -+ -+ runtime->private_data = audio; -+ runtime->hw = audio_hw_info; -+ snd_pcm_limit_hw_rates(runtime); -+ runtime->hw.channels_max = 2; -+ -+ audio->substream = substream; -+ -+ /* Add the QoS request and set the latency to 0 */ -+ pm_qos_add_request(&audio->pm_qos, PM_QOS_CPU_DMA_LATENCY, 0); -+ -+ return 0; -+} -+ -+static int audio_pcm_close(struct snd_pcm_substream *substream) -+{ -+ struct audio_dev *audio = substream->private_data; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&audio->lock, flags); -+ -+ /* Remove the QoS request */ -+ pm_qos_remove_request(&audio->pm_qos); -+ -+ audio->substream = NULL; -+ spin_unlock_irqrestore(&audio->lock, flags); -+ -+ return 0; -+} -+ -+static int audio_pcm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ unsigned int channels = params_channels(params); -+ unsigned int rate = params_rate(params); -+ -+ if (rate != SAMPLE_RATE) -+ return -EINVAL; -+ if (channels != 2) -+ return -EINVAL; -+ -+ return snd_pcm_lib_alloc_vmalloc_buffer(substream, -+ params_buffer_bytes(params)); -+} -+ -+static int audio_pcm_hw_free(struct snd_pcm_substream *substream) -+{ -+ return snd_pcm_lib_free_vmalloc_buffer(substream); -+} -+ -+static int audio_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct audio_dev *audio = runtime->private_data; -+ -+ audio->period = snd_pcm_lib_period_bytes(substream); -+ audio->period_offset = 0; -+ audio->buffer_start = runtime->dma_area; -+ audio->buffer_end = audio->buffer_start -+ + snd_pcm_lib_buffer_bytes(substream); -+ audio->buffer_pos = audio->buffer_start; -+ -+ return 0; -+} -+ -+static snd_pcm_uframes_t audio_pcm_pointer(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ struct audio_dev *audio = runtime->private_data; -+ ssize_t bytes = audio->buffer_pos - audio->buffer_start; -+ -+ /* return offset of next frame to fill in our buffer */ -+ return bytes_to_frames(runtime, bytes); -+} -+ -+static int audio_pcm_playback_trigger(struct snd_pcm_substream *substream, -+ int cmd) -+{ -+ struct audio_dev *audio = substream->runtime->private_data; -+ int ret = 0; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ audio_pcm_playback_start(audio); -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ audio_pcm_playback_stop(audio); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static struct audio_dev _audio_dev = { -+ .func = { -+ .name = "audio_source", -+ .bind = audio_bind, -+ .unbind = audio_unbind, -+ .set_alt = audio_set_alt, -+ .setup = audio_setup, -+ .disable = audio_disable, -+ .free_func = audio_free_func, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(_audio_dev.lock), -+ .idle_reqs = LIST_HEAD_INIT(_audio_dev.idle_reqs), -+}; -+ -+static struct snd_pcm_ops audio_playback_ops = { -+ .open = audio_pcm_open, -+ .close = audio_pcm_close, -+ .ioctl = snd_pcm_lib_ioctl, -+ .hw_params = audio_pcm_hw_params, -+ .hw_free = audio_pcm_hw_free, -+ .prepare = audio_pcm_prepare, -+ .trigger = audio_pcm_playback_trigger, -+ .pointer = audio_pcm_pointer, -+}; -+ -+int audio_source_bind_config(struct usb_configuration *c, -+ struct audio_source_config *config) -+{ -+ struct audio_dev *audio; -+ int err; -+ -+ config->card = -1; -+ config->device = -1; -+ -+ audio = &_audio_dev; -+ -+ err = snd_card_setup(c, config); -+ if (err) -+ return err; -+ -+ err = usb_add_function(c, &audio->func); -+ if (err) -+ goto add_fail; -+ -+ return 0; -+ -+add_fail: -+ snd_card_free(audio->card); -+ return err; -+} -+ -+static int snd_card_setup(struct usb_configuration *c, -+ struct audio_source_config *config) -+{ -+ struct audio_dev *audio; -+ struct snd_card *card; -+ struct snd_pcm *pcm; -+ int err; -+ -+ audio = &_audio_dev; -+ -+ err = snd_card_new(&c->cdev->gadget->dev, -+ SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, -+ THIS_MODULE, 0, &card); -+ if (err) -+ return err; -+ -+ err = snd_pcm_new(card, "USB audio source", 0, 1, 0, &pcm); -+ if (err) -+ goto pcm_fail; -+ -+ pcm->private_data = audio; -+ pcm->info_flags = 0; -+ audio->pcm = pcm; -+ -+ strlcpy(pcm->name, "USB gadget audio", sizeof(pcm->name)); -+ -+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &audio_playback_ops); -+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, -+ NULL, 0, 64 * 1024); -+ -+ strlcpy(card->driver, "audio_source", sizeof(card->driver)); -+ strlcpy(card->shortname, card->driver, sizeof(card->shortname)); -+ strlcpy(card->longname, "USB accessory audio source", -+ sizeof(card->longname)); -+ -+ err = snd_card_register(card); -+ if (err) -+ goto register_fail; -+ -+ config->card = pcm->card->number; -+ config->device = pcm->device; -+ audio->card = card; -+ return 0; -+ -+register_fail: -+pcm_fail: -+ snd_card_free(audio->card); -+ return err; -+} -+ -+static struct audio_source_instance *to_audio_source_instance( -+ struct config_item *item) -+{ -+ return container_of(to_config_group(item), struct audio_source_instance, -+ func_inst.group); -+} -+ -+static struct audio_source_instance *to_fi_audio_source( -+ const struct usb_function_instance *fi) -+{ -+ return container_of(fi, struct audio_source_instance, func_inst); -+} -+ -+static void audio_source_attr_release(struct config_item *item) -+{ -+ struct audio_source_instance *fi_audio = to_audio_source_instance(item); -+ -+ usb_put_function_instance(&fi_audio->func_inst); -+} -+ -+static int audio_source_set_inst_name(struct usb_function_instance *fi, -+ const char *name) -+{ -+ struct audio_source_instance *fi_audio; -+ char *ptr; -+ int name_len; -+ -+ name_len = strlen(name) + 1; -+ if (name_len > MAX_INST_NAME_LEN) -+ return -ENAMETOOLONG; -+ -+ ptr = kstrndup(name, name_len, GFP_KERNEL); -+ if (!ptr) -+ return -ENOMEM; -+ -+ fi_audio = to_fi_audio_source(fi); -+ fi_audio->name = ptr; -+ -+ return 0; -+} -+ -+static void audio_source_free_inst(struct usb_function_instance *fi) -+{ -+ struct audio_source_instance *fi_audio; -+ -+ fi_audio = to_fi_audio_source(fi); -+ device_destroy(fi_audio->audio_device->class, -+ fi_audio->audio_device->devt); -+ kfree(fi_audio->name); -+ kfree(fi_audio->config); -+} -+ -+static ssize_t audio_source_pcm_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct audio_source_instance *fi_audio = dev_get_drvdata(dev); -+ struct audio_source_config *config = fi_audio->config; -+ -+ /* print PCM card and device numbers */ -+ return sprintf(buf, "%d %d\n", config->card, config->device); -+} -+ -+struct device *create_function_device(char *name); -+ -+static struct usb_function_instance *audio_source_alloc_inst(void) -+{ -+ struct audio_source_instance *fi_audio; -+ struct device_attribute **attrs; -+ struct device_attribute *attr; -+ struct device *dev; -+ void *err_ptr; -+ int err = 0; -+ -+ fi_audio = kzalloc(sizeof(*fi_audio), GFP_KERNEL); -+ if (!fi_audio) -+ return ERR_PTR(-ENOMEM); -+ -+ fi_audio->func_inst.set_inst_name = audio_source_set_inst_name; -+ fi_audio->func_inst.free_func_inst = audio_source_free_inst; -+ -+ fi_audio->config = kzalloc(sizeof(struct audio_source_config), -+ GFP_KERNEL); -+ if (!fi_audio->config) { -+ err_ptr = ERR_PTR(-ENOMEM); -+ goto fail_audio; -+ } -+ -+ config_group_init_type_name(&fi_audio->func_inst.group, "", -+ &audio_source_func_type); -+ dev = create_function_device("f_audio_source"); -+ -+ if (IS_ERR(dev)) { -+ err_ptr = dev; -+ goto fail_audio_config; -+ } -+ -+ fi_audio->config->card = -1; -+ fi_audio->config->device = -1; -+ fi_audio->audio_device = dev; -+ -+ attrs = audio_source_function_attributes; -+ if (attrs) { -+ while ((attr = *attrs++) && !err) -+ err = device_create_file(dev, attr); -+ if (err) { -+ err_ptr = ERR_PTR(-EINVAL); -+ goto fail_device; -+ } -+ } -+ -+ dev_set_drvdata(dev, fi_audio); -+ _audio_dev.config = fi_audio->config; -+ -+ return &fi_audio->func_inst; -+ -+fail_device: -+ device_destroy(dev->class, dev->devt); -+fail_audio_config: -+ kfree(fi_audio->config); -+fail_audio: -+ kfree(fi_audio); -+ return err_ptr; -+ -+} -+ -+static struct usb_function *audio_source_alloc(struct usb_function_instance *fi) -+{ -+ return &_audio_dev.func; -+} -+ -+DECLARE_USB_FUNCTION_INIT(audio_source, audio_source_alloc_inst, -+ audio_source_alloc); -+MODULE_LICENSE("GPL"); diff --git a/patches/ANDROID-usb-gadget-f_midi-create-F_midi-device.patch b/patches/ANDROID-usb-gadget-f_midi-create-F_midi-device.patch deleted file mode 100644 index cf8585458ee2e5fc5a38e939364741c870e2a7ed..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-f_midi-create-F_midi-device.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Badhri Jagan Sridharan -Date: Wed, 2 Sep 2015 22:49:10 -0700 -Subject: ANDROID: usb: gadget: f_midi: create F_midi device - -Android frameworks relies on the alsa -config reported by the f_midi device. - -Bug: 111003288 -Bug: 120441124 -Change-Id: I0695e00b166fd953f50acea93802245b0d5a5240 -[badhri: The framework should be moved away from this] -Signed-off-by: Badhri Jagan Sridharan ---- - drivers/usb/gadget/function/f_midi.c | 65 ++++++++++++++++++++++++++++ - 1 file changed, 65 insertions(+) - -diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c -index 46af0aa07e2e..2a86b3cf313f 100644 ---- a/drivers/usb/gadget/function/f_midi.c -+++ b/drivers/usb/gadget/function/f_midi.c -@@ -1216,6 +1216,65 @@ static void f_midi_free_inst(struct usb_function_instance *f) - } - } - -+#ifdef CONFIG_USB_CONFIGFS_UEVENT -+extern struct device *create_function_device(char *name); -+static ssize_t alsa_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct usb_function_instance *fi_midi = dev_get_drvdata(dev); -+ struct f_midi *midi; -+ -+ if (!fi_midi->f) -+ dev_warn(dev, "f_midi: function not set\n"); -+ -+ if (fi_midi && fi_midi->f) { -+ midi = func_to_midi(fi_midi->f); -+ if (midi->rmidi && midi->rmidi->card) -+ return sprintf(buf, "%d %d\n", -+ midi->rmidi->card->number, midi->rmidi->device); -+ } -+ -+ /* print PCM card and device numbers */ -+ return sprintf(buf, "%d %d\n", -1, -1); -+} -+ -+static DEVICE_ATTR(alsa, S_IRUGO, alsa_show, NULL); -+ -+static struct device_attribute *alsa_function_attributes[] = { -+ &dev_attr_alsa, -+ NULL -+}; -+ -+static int create_alsa_device(struct usb_function_instance *fi) -+{ -+ struct device *dev; -+ struct device_attribute **attrs; -+ struct device_attribute *attr; -+ int err = 0; -+ -+ dev = create_function_device("f_midi"); -+ if (IS_ERR(dev)) -+ return PTR_ERR(dev); -+ -+ attrs = alsa_function_attributes; -+ if (attrs) { -+ while ((attr = *attrs++) && !err) -+ err = device_create_file(dev, attr); -+ if (err) { -+ device_destroy(dev->class, dev->devt); -+ return -EINVAL; -+ } -+ } -+ dev_set_drvdata(dev, fi); -+ return 0; -+} -+#else -+static int create_alsa_device(struct usb_function_instance *fi) -+{ -+ return 0; -+} -+#endif -+ - static struct usb_function_instance *f_midi_alloc_inst(void) - { - struct f_midi_opts *opts; -@@ -1234,6 +1293,11 @@ static struct usb_function_instance *f_midi_alloc_inst(void) - opts->out_ports = 1; - opts->refcnt = 1; - -+ if (create_alsa_device(&opts->func_inst)) { -+ kfree(opts); -+ return ERR_PTR(-ENODEV); -+ } -+ - config_group_init_type_name(&opts->func_inst.group, "", - &midi_func_type); - -@@ -1341,6 +1405,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) - midi->func.disable = f_midi_disable; - midi->func.free_func = f_midi_free; - -+ fi->f = &midi->func; - return &midi->func; - - setup_fail: diff --git a/patches/ANDROID-usb-gadget-f_midi-set-fi-f-to-NULL-when-free-f_midi-function.patch b/patches/ANDROID-usb-gadget-f_midi-set-fi-f-to-NULL-when-free-f_midi-function.patch deleted file mode 100644 index 05fe9c48df43e326c4bd005428a4f99e1edc18db..0000000000000000000000000000000000000000 --- a/patches/ANDROID-usb-gadget-f_midi-set-fi-f-to-NULL-when-free-f_midi-function.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Winter Wang -Date: Fri, 20 May 2016 11:05:00 +0800 -Subject: ANDROID: usb: gadget: f_midi: set fi->f to NULL when free f_midi - function - -fi->f is set in f_midi's alloc_func, need to clean this to -NULL in free_func, otherwise on ConfigFS's function switch, -midi->usb_function it self is freed, fi->f will be a wild -pointer and run into below kernel panic: ---------------- -[ 58.950628] Unable to handle kernel paging request at virtual address 63697664 -[ 58.957869] pgd = c0004000 -[ 58.960583] [63697664] *pgd=00000000 -[ 58.964185] Internal error: Oops: 80000005 [#1] PREEMPT SMP ARM -[ 58.970111] Modules linked in: -[ 58.973191] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.1.15-03504-g34c857c-dirty #89 -[ 58.981024] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) -[ 58.987557] task: c110bd70 ti: c1100000 task.ti: c1100000 -[ 58.992962] PC is at 0x63697664 -[ 58.996120] LR is at android_setup+0x78/0x138 -<..snip..> -[ 60.044980] 1fc0: ffffffff ffffffff c1000684 00000000 00000000 c108ecd0 c11f7294 c11039c0 -[ 60.053181] 1fe0: c108eccc c110d148 1000406a 412fc09a 00000000 1000807c 00000000 00000000 -[ 60.061420] [] (android_setup) from [] (udc_irq+0x758/0x1034) -[ 60.068951] [] (udc_irq) from [] (handle_irq_event_percpu+0x50/0x254) -[ 60.077165] [] (handle_irq_event_percpu) from [] (handle_irq_event+0x3c/0x5c) -[ 60.086072] [] (handle_irq_event) from [] (handle_fasteoi_irq+0xe0/0x198) -[ 60.094630] [] (handle_fasteoi_irq) from [] (generic_handle_irq+0x2c/0x3c) -[ 60.103271] [] (generic_handle_irq) from [] (__handle_domain_irq+0x7c/0xec) -[ 60.112000] [] (__handle_domain_irq) from [] (gic_handle_irq+0x24/0x5c) --------------- - -Bug: 111003288 -Bug: 120441124 -Change-Id: Iaf7cc809379c184048a2d9ab1f59e71ebaa3416e -Signed-off-by: Winter Wang ---- - drivers/usb/gadget/function/f_midi.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c -index 2a86b3cf313f..4713a1c7f622 100644 ---- a/drivers/usb/gadget/function/f_midi.c -+++ b/drivers/usb/gadget/function/f_midi.c -@@ -1318,6 +1318,7 @@ static void f_midi_free(struct usb_function *f) - kfifo_free(&midi->in_req_fifo); - kfree(midi); - free = true; -+ opts->func_inst.f = NULL; - } - mutex_unlock(&opts->lock); - diff --git a/patches/ANDROID-vfs-Add-permission2-for-filesystems-with-per-mount-permissions.patch b/patches/ANDROID-vfs-Add-permission2-for-filesystems-with-per-mount-permissions.patch deleted file mode 100644 index cf21b50796a54674299f07fd00ec64eb8f39d8d6..0000000000000000000000000000000000000000 --- a/patches/ANDROID-vfs-Add-permission2-for-filesystems-with-per-mount-permissions.patch +++ /dev/null @@ -1,892 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Wed, 26 Oct 2016 16:27:45 -0700 -Subject: ANDROID: vfs: Add permission2 for filesystems with per mount - permissions - -This allows filesystems to use their mount private data to -influence the permssions they return in permission2. It has -been separated into a new call to avoid disrupting current -permission users. - -Test: HiKey/X15 + Pie + android-mainline, - and HiKey + AOSP Maser + android-mainline, - directories under /sdcard created, - output of mount is right, - CTS test collecting device infor works - -Bug: 35848445 -Change-Id: I9d416e3b8b6eca84ef3e336bd2af89ddd51df6ca -Signed-off-by: Daniel Rosenberg -[AmitP: Minor refactoring of original patch to align with - changes from the following upstream commit - 4bfd054ae11e ("fs: fold __inode_permission() into inode_permission()"). - Also introduce vfs_mkobj2(), because do_create() - moved from using vfs_create() to vfs_mkobj() - eecec19d9e70 ("mqueue: switch to vfs_mkobj(), quit abusing ->d_fsdata") - do_create() is dropped/cleaned-up upstream so a - minor refactoring there as well. - 066cc813e94a ("do_mq_open(): move all work prior to dentry_open() into a helper")] -Signed-off-by: Amit Pundir -[astrachan: Folded the following changes into this patch: - f46c9d62dd81 ("ANDROID: fs: Export vfs_rmdir2") - 9992eb8b9a1e ("ANDROID: xattr: Pass EOPNOTSUPP to permission2")] -Signed-off-by: Alistair Strachan -Signed-off-by: Yongqin Liu ---- - fs/attr.c | 2 +- - fs/exec.c | 2 +- - fs/namei.c | 187 ++++++++++++++++++++--------- - fs/notify/fanotify/fanotify_user.c | 2 +- - fs/notify/inotify/inotify_user.c | 2 +- - fs/open.c | 13 +- - fs/xattr.c | 2 +- - include/linux/fs.h | 13 ++ - include/linux/namei.h | 1 + - ipc/mqueue.c | 14 +-- - security/inode.c | 2 +- - 11 files changed, 168 insertions(+), 72 deletions(-) - -diff --git a/fs/attr.c b/fs/attr.c -index 0a7f9d67bb35..be094ea6a330 100644 ---- a/fs/attr.c -+++ b/fs/attr.c -@@ -250,7 +250,7 @@ int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * - return -EPERM; - - if (!inode_owner_or_capable(inode)) { -- error = inode_permission(inode, MAY_WRITE); -+ error = inode_permission2(mnt, inode, MAY_WRITE); - if (error) - return error; - } -diff --git a/fs/exec.c b/fs/exec.c -index 555e93c7dec8..34df3b6cf448 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -1313,7 +1313,7 @@ EXPORT_SYMBOL(flush_old_exec); - void would_dump(struct linux_binprm *bprm, struct file *file) - { - struct inode *inode = file_inode(file); -- if (inode_permission(inode, MAY_READ) < 0) { -+ if (inode_permission2(file->f_path.mnt, inode, MAY_READ) < 0) { - struct user_namespace *old, *user_ns; - bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; - -diff --git a/fs/namei.c b/fs/namei.c -index 8a77269e644f..819aa30eea6e 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -377,9 +377,11 @@ EXPORT_SYMBOL(generic_permission); - * flag in inode->i_opflags, that says "this has not special - * permission function, use the fast case". - */ --static inline int do_inode_permission(struct inode *inode, int mask) -+static inline int do_inode_permission(struct vfsmount *mnt, struct inode *inode, int mask) - { - if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) { -+ if (likely(mnt && inode->i_op->permission2)) -+ return inode->i_op->permission2(mnt, inode, mask); - if (likely(inode->i_op->permission)) - return inode->i_op->permission(inode, mask); - -@@ -412,7 +414,8 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask) - } - - /** -- * inode_permission - Check for access rights to a given inode -+ * inode_permission2 - Check for access rights to a given inode -+ * @mnt: - * @inode: Inode to check permission on - * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) - * -@@ -422,7 +425,7 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask) - * - * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask. - */ --int inode_permission(struct inode *inode, int mask) -+int inode_permission2(struct vfsmount *mnt, struct inode *inode, int mask) - { - int retval; - -@@ -446,7 +449,7 @@ int inode_permission(struct inode *inode, int mask) - return -EACCES; - } - -- retval = do_inode_permission(inode, mask); -+ retval = do_inode_permission(mnt, inode, mask); - if (retval) - return retval; - -@@ -454,7 +457,14 @@ int inode_permission(struct inode *inode, int mask) - if (retval) - return retval; - -- return security_inode_permission(inode, mask); -+ retval = security_inode_permission(inode, mask); -+ return retval; -+} -+EXPORT_SYMBOL(inode_permission2); -+ -+int inode_permission(struct inode *inode, int mask) -+{ -+ return inode_permission2(NULL, inode, mask); - } - EXPORT_SYMBOL(inode_permission); - -@@ -1685,13 +1695,13 @@ static struct dentry *lookup_slow(const struct qstr *name, - static inline int may_lookup(struct nameidata *nd) - { - if (nd->flags & LOOKUP_RCU) { -- int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK); -+ int err = inode_permission2(nd->path.mnt, nd->inode, MAY_EXEC|MAY_NOT_BLOCK); - if (err != -ECHILD) - return err; - if (unlazy_walk(nd)) - return -ECHILD; - } -- return inode_permission(nd->inode, MAY_EXEC); -+ return inode_permission2(nd->path.mnt, nd->inode, MAY_EXEC); - } - - static inline int handle_dots(struct nameidata *nd, int type) -@@ -2445,8 +2455,8 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, - } - EXPORT_SYMBOL(vfs_path_lookup); - --static int lookup_one_len_common(const char *name, struct dentry *base, -- int len, struct qstr *this) -+static int lookup_one_len_common(const char *name, struct vfsmount *mnt, -+ struct dentry *base, int len, struct qstr *this) - { - this->name = name; - this->len = len; -@@ -2474,7 +2484,7 @@ static int lookup_one_len_common(const char *name, struct dentry *base, - return err; - } - -- return inode_permission(base->d_inode, MAY_EXEC); -+ return inode_permission2(mnt, base->d_inode, MAY_EXEC); - } - - /** -@@ -2498,7 +2508,7 @@ struct dentry *try_lookup_one_len(const char *name, struct dentry *base, int len - - WARN_ON_ONCE(!inode_is_locked(base->d_inode)); - -- err = lookup_one_len_common(name, base, len, &this); -+ err = lookup_one_len_common(name, NULL, base, len, &this); - if (err) - return ERR_PTR(err); - -@@ -2517,7 +2527,7 @@ EXPORT_SYMBOL(try_lookup_one_len); - * - * The caller must hold base->i_mutex. - */ --struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) -+struct dentry *lookup_one_len2(const char *name, struct vfsmount *mnt, struct dentry *base, int len) - { - struct dentry *dentry; - struct qstr this; -@@ -2525,13 +2535,19 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) - - WARN_ON_ONCE(!inode_is_locked(base->d_inode)); - -- err = lookup_one_len_common(name, base, len, &this); -+ err = lookup_one_len_common(name, mnt, base, len, &this); - if (err) - return ERR_PTR(err); - - dentry = lookup_dcache(&this, base, 0); - return dentry ? dentry : __lookup_slow(&this, base, 0); - } -+EXPORT_SYMBOL(lookup_one_len2); -+ -+struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) -+{ -+ return lookup_one_len2(name, NULL, base, len); -+} - EXPORT_SYMBOL(lookup_one_len); - - /** -@@ -2553,7 +2569,7 @@ struct dentry *lookup_one_len_unlocked(const char *name, - int err; - struct dentry *ret; - -- err = lookup_one_len_common(name, base, len, &this); -+ err = lookup_one_len_common(name, NULL, base, len, &this); - if (err) - return ERR_PTR(err); - -@@ -2777,7 +2793,7 @@ EXPORT_SYMBOL(__check_sticky); - * 11. We don't allow removal of NFS sillyrenamed files; it's handled by - * nfs_async_unlink(). - */ --static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) -+static int may_delete(struct vfsmount *mnt, struct inode *dir, struct dentry *victim, bool isdir) - { - struct inode *inode = d_backing_inode(victim); - int error; -@@ -2794,7 +2810,7 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) - - audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); - -- error = inode_permission(dir, MAY_WRITE | MAY_EXEC); -+ error = inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC); - if (error) - return error; - if (IS_APPEND(dir)) -@@ -2826,7 +2842,7 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) - * 4. We should have write and exec permissions on dir - * 5. We can't do it if dir is immutable (done in permission()) - */ --static inline int may_create(struct inode *dir, struct dentry *child) -+static inline int may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child) - { - struct user_namespace *s_user_ns; - audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); -@@ -2838,7 +2854,7 @@ static inline int may_create(struct inode *dir, struct dentry *child) - if (!kuid_has_mapping(s_user_ns, current_fsuid()) || - !kgid_has_mapping(s_user_ns, current_fsgid())) - return -EOVERFLOW; -- return inode_permission(dir, MAY_WRITE | MAY_EXEC); -+ return inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC); - } - - /* -@@ -2885,10 +2901,10 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) - } - EXPORT_SYMBOL(unlock_rename); - --int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -- bool want_excl) -+int vfs_create2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, -+ umode_t mode, bool want_excl) - { -- int error = may_create(dir, dentry); -+ int error = may_create(mnt, dir, dentry); - if (error) - return error; - -@@ -2904,14 +2920,21 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, - fsnotify_create(dir, dentry); - return error; - } -+EXPORT_SYMBOL(vfs_create2); -+ -+int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl) -+{ -+ return vfs_create2(NULL, dir, dentry, mode, want_excl); -+} - EXPORT_SYMBOL(vfs_create); - --int vfs_mkobj(struct dentry *dentry, umode_t mode, -+int vfs_mkobj2(struct vfsmount *mnt, struct dentry *dentry, umode_t mode, - int (*f)(struct dentry *, umode_t, void *), - void *arg) - { - struct inode *dir = dentry->d_parent->d_inode; -- int error = may_create(dir, dentry); -+ int error = may_create(mnt, dir, dentry); - if (error) - return error; - -@@ -2925,6 +2948,15 @@ int vfs_mkobj(struct dentry *dentry, umode_t mode, - fsnotify_create(dir, dentry); - return error; - } -+EXPORT_SYMBOL(vfs_mkobj2); -+ -+ -+int vfs_mkobj(struct dentry *dentry, umode_t mode, -+ int (*f)(struct dentry *, umode_t, void *), -+ void *arg) -+{ -+ return vfs_mkobj2(NULL, dentry, mode, f, arg); -+} - EXPORT_SYMBOL(vfs_mkobj); - - bool may_open_dev(const struct path *path) -@@ -2936,6 +2968,7 @@ bool may_open_dev(const struct path *path) - static int may_open(const struct path *path, int acc_mode, int flag) - { - struct dentry *dentry = path->dentry; -+ struct vfsmount *mnt = path->mnt; - struct inode *inode = dentry->d_inode; - int error; - -@@ -2960,7 +2993,7 @@ static int may_open(const struct path *path, int acc_mode, int flag) - break; - } - -- error = inode_permission(inode, MAY_OPEN | acc_mode); -+ error = inode_permission2(mnt, inode, MAY_OPEN | acc_mode); - if (error) - return error; - -@@ -3022,7 +3055,7 @@ static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t m - !kgid_has_mapping(s_user_ns, current_fsgid())) - return -EOVERFLOW; - -- error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC); -+ error = inode_permission2(dir->mnt, dir->dentry->d_inode, MAY_WRITE | MAY_EXEC); - if (error) - return error; - -@@ -3430,7 +3463,8 @@ struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag) - int error; - - /* we want directory to be writable */ -- error = inode_permission(dir, MAY_WRITE | MAY_EXEC); -+ error = inode_permission2(ERR_PTR(-EOPNOTSUPP), dir, -+ MAY_WRITE | MAY_EXEC); - if (error) - goto out_err; - error = -EOPNOTSUPP; -@@ -3685,9 +3719,9 @@ inline struct dentry *user_path_create(int dfd, const char __user *pathname, - } - EXPORT_SYMBOL(user_path_create); - --int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) -+int vfs_mknod2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) - { -- int error = may_create(dir, dentry); -+ int error = may_create(mnt, dir, dentry); - - if (error) - return error; -@@ -3711,6 +3745,12 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) - fsnotify_create(dir, dentry); - return error; - } -+EXPORT_SYMBOL(vfs_mknod2); -+ -+int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) -+{ -+ return vfs_mknod2(NULL, dir, dentry, mode, dev); -+} - EXPORT_SYMBOL(vfs_mknod); - - static int may_mknod(umode_t mode) -@@ -3753,12 +3793,12 @@ long do_mknodat(int dfd, const char __user *filename, umode_t mode, - goto out; - switch (mode & S_IFMT) { - case 0: case S_IFREG: -- error = vfs_create(path.dentry->d_inode,dentry,mode,true); -+ error = vfs_create2(path.mnt, path.dentry->d_inode,dentry,mode,true); - if (!error) - ima_post_path_mknod(dentry); - break; - case S_IFCHR: case S_IFBLK: -- error = vfs_mknod(path.dentry->d_inode,dentry,mode, -+ error = vfs_mknod2(path.mnt, path.dentry->d_inode,dentry,mode, - new_decode_dev(dev)); - break; - case S_IFIFO: case S_IFSOCK: -@@ -3785,9 +3825,9 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d - return do_mknodat(AT_FDCWD, filename, mode, dev); - } - --int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -+int vfs_mkdir2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, umode_t mode) - { -- int error = may_create(dir, dentry); -+ int error = may_create(mnt, dir, dentry); - unsigned max_links = dir->i_sb->s_max_links; - - if (error) -@@ -3809,6 +3849,12 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) - fsnotify_mkdir(dir, dentry); - return error; - } -+EXPORT_SYMBOL(vfs_mkdir2); -+ -+int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ return vfs_mkdir2(NULL, dir, dentry, mode); -+} - EXPORT_SYMBOL(vfs_mkdir); - - long do_mkdirat(int dfd, const char __user *pathname, umode_t mode) -@@ -3827,7 +3873,7 @@ long do_mkdirat(int dfd, const char __user *pathname, umode_t mode) - mode &= ~current_umask(); - error = security_path_mkdir(&path, dentry, mode); - if (!error) -- error = vfs_mkdir(path.dentry->d_inode, dentry, mode); -+ error = vfs_mkdir2(path.mnt, path.dentry->d_inode, dentry, mode); - done_path_create(&path, dentry); - if (retry_estale(error, lookup_flags)) { - lookup_flags |= LOOKUP_REVAL; -@@ -3846,9 +3892,9 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode) - return do_mkdirat(AT_FDCWD, pathname, mode); - } - --int vfs_rmdir(struct inode *dir, struct dentry *dentry) -+int vfs_rmdir2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry) - { -- int error = may_delete(dir, dentry, 1); -+ int error = may_delete(mnt, dir, dentry, 1); - - if (error) - return error; -@@ -3884,6 +3930,12 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) - d_delete(dentry); - return error; - } -+EXPORT_SYMBOL(vfs_rmdir2); -+ -+int vfs_rmdir(struct inode *dir, struct dentry *dentry) -+{ -+ return vfs_rmdir2(NULL, dir, dentry); -+} - EXPORT_SYMBOL(vfs_rmdir); - - long do_rmdir(int dfd, const char __user *pathname) -@@ -3929,7 +3981,7 @@ long do_rmdir(int dfd, const char __user *pathname) - error = security_path_rmdir(&path, dentry); - if (error) - goto exit3; -- error = vfs_rmdir(path.dentry->d_inode, dentry); -+ error = vfs_rmdir2(path.mnt, path.dentry->d_inode, dentry); - exit3: - dput(dentry); - exit2: -@@ -3968,10 +4020,10 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname) - * be appropriate for callers that expect the underlying filesystem not - * to be NFS exported. - */ --int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode) -+int vfs_unlink2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, struct inode **delegated_inode) - { - struct inode *target = dentry->d_inode; -- int error = may_delete(dir, dentry, 0); -+ int error = may_delete(mnt, dir, dentry, 0); - - if (error) - return error; -@@ -4007,6 +4059,12 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate - - return error; - } -+EXPORT_SYMBOL(vfs_unlink2); -+ -+int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode) -+{ -+ return vfs_unlink2(NULL, dir, dentry, delegated_inode); -+} - EXPORT_SYMBOL(vfs_unlink); - - /* -@@ -4052,7 +4110,7 @@ long do_unlinkat(int dfd, struct filename *name) - error = security_path_unlink(&path, dentry); - if (error) - goto exit2; -- error = vfs_unlink(path.dentry->d_inode, dentry, &delegated_inode); -+ error = vfs_unlink2(path.mnt, path.dentry->d_inode, dentry, &delegated_inode); - exit2: - dput(dentry); - } -@@ -4102,9 +4160,9 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname) - return do_unlinkat(AT_FDCWD, getname(pathname)); - } - --int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) -+int vfs_symlink2(struct vfsmount *mnt, struct inode *dir, struct dentry *dentry, const char *oldname) - { -- int error = may_create(dir, dentry); -+ int error = may_create(mnt, dir, dentry); - - if (error) - return error; -@@ -4121,6 +4179,12 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) - fsnotify_create(dir, dentry); - return error; - } -+EXPORT_SYMBOL(vfs_symlink2); -+ -+int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) -+{ -+ return vfs_symlink2(NULL, dir, dentry, oldname); -+} - EXPORT_SYMBOL(vfs_symlink); - - long do_symlinkat(const char __user *oldname, int newdfd, -@@ -4143,7 +4207,7 @@ long do_symlinkat(const char __user *oldname, int newdfd, - - error = security_path_symlink(&path, dentry, from->name); - if (!error) -- error = vfs_symlink(path.dentry->d_inode, dentry, from->name); -+ error = vfs_symlink2(path.mnt, path.dentry->d_inode, dentry, from->name); - done_path_create(&path, dentry); - if (retry_estale(error, lookup_flags)) { - lookup_flags |= LOOKUP_REVAL; -@@ -4184,7 +4248,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn - * be appropriate for callers that expect the underlying filesystem not - * to be NFS exported. - */ --int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode) -+int vfs_link2(struct vfsmount *mnt, struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode) - { - struct inode *inode = old_dentry->d_inode; - unsigned max_links = dir->i_sb->s_max_links; -@@ -4193,7 +4257,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de - if (!inode) - return -ENOENT; - -- error = may_create(dir, new_dentry); -+ error = may_create(mnt, dir, new_dentry); - if (error) - return error; - -@@ -4243,6 +4307,12 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de - fsnotify_link(dir, inode, new_dentry); - return error; - } -+EXPORT_SYMBOL(vfs_link2); -+ -+int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode) -+{ -+ return vfs_link2(NULL, old_dentry, dir, new_dentry, delegated_inode); -+} - EXPORT_SYMBOL(vfs_link); - - /* -@@ -4298,7 +4368,7 @@ int do_linkat(int olddfd, const char __user *oldname, int newdfd, - error = security_path_link(old_path.dentry, &new_path, new_dentry); - if (error) - goto out_dput; -- error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode); -+ error = vfs_link2(old_path.mnt, old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode); - out_dput: - done_path_create(&new_path, new_dentry); - if (delegated_inode) { -@@ -4380,7 +4450,8 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname - * ->i_mutex on parents, which works but leads to some truly excessive - * locking]. - */ --int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+int vfs_rename2(struct vfsmount *mnt, -+ struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, - struct inode **delegated_inode, unsigned int flags) - { -@@ -4395,19 +4466,19 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - if (source == target) - return 0; - -- error = may_delete(old_dir, old_dentry, is_dir); -+ error = may_delete(mnt, old_dir, old_dentry, is_dir); - if (error) - return error; - - if (!target) { -- error = may_create(new_dir, new_dentry); -+ error = may_create(mnt, new_dir, new_dentry); - } else { - new_is_dir = d_is_dir(new_dentry); - - if (!(flags & RENAME_EXCHANGE)) -- error = may_delete(new_dir, new_dentry, is_dir); -+ error = may_delete(mnt, new_dir, new_dentry, is_dir); - else -- error = may_delete(new_dir, new_dentry, new_is_dir); -+ error = may_delete(mnt, new_dir, new_dentry, new_is_dir); - } - if (error) - return error; -@@ -4421,12 +4492,12 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - */ - if (new_dir != old_dir) { - if (is_dir) { -- error = inode_permission(source, MAY_WRITE); -+ error = inode_permission2(mnt, source, MAY_WRITE); - if (error) - return error; - } - if ((flags & RENAME_EXCHANGE) && new_is_dir) { -- error = inode_permission(target, MAY_WRITE); -+ error = inode_permission2(mnt, target, MAY_WRITE); - if (error) - return error; - } -@@ -4503,6 +4574,14 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - - return error; - } -+EXPORT_SYMBOL(vfs_rename2); -+ -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry, -+ struct inode **delegated_inode, unsigned int flags) -+{ -+ return vfs_rename2(NULL, old_dir, old_dentry, new_dir, new_dentry, delegated_inode, flags); -+} - EXPORT_SYMBOL(vfs_rename); - - static int do_renameat2(int olddfd, const char __user *oldname, int newdfd, -@@ -4616,7 +4695,7 @@ static int do_renameat2(int olddfd, const char __user *oldname, int newdfd, - &new_path, new_dentry, flags); - if (error) - goto exit5; -- error = vfs_rename(old_path.dentry->d_inode, old_dentry, -+ error = vfs_rename2(old_path.mnt, old_path.dentry->d_inode, old_dentry, - new_path.dentry->d_inode, new_dentry, - &delegated_inode, flags); - exit5: -@@ -4667,7 +4746,7 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna - - int vfs_whiteout(struct inode *dir, struct dentry *dentry) - { -- int error = may_create(dir, dentry); -+ int error = may_create(NULL, dir, dentry); - if (error) - return error; - -diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c -index 8508ab575017..2e667cb8d69e 100644 ---- a/fs/notify/fanotify/fanotify_user.c -+++ b/fs/notify/fanotify/fanotify_user.c -@@ -567,7 +567,7 @@ static int fanotify_find_path(int dfd, const char __user *filename, - } - - /* you can only watch an inode if you have read permissions on it */ -- ret = inode_permission(path->dentry->d_inode, MAY_READ); -+ ret = inode_permission2(path->mnt, path->dentry->d_inode, MAY_READ); - if (ret) { - path_put(path); - goto out; -diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c -index 107537a543fd..3e66e6c8f53a 100644 ---- a/fs/notify/inotify/inotify_user.c -+++ b/fs/notify/inotify/inotify_user.c -@@ -341,7 +341,7 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, - if (error) - return error; - /* you can only watch an inode if you have read permissions on it */ -- error = inode_permission(path->dentry->d_inode, MAY_READ); -+ error = inode_permission2(path->mnt, path->dentry->d_inode, MAY_READ); - if (error) { - path_put(path); - return error; -diff --git a/fs/open.c b/fs/open.c -index a189284464a0..681affa0cb37 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -90,7 +90,7 @@ long vfs_truncate(const struct path *path, loff_t length) - if (error) - goto out; - -- error = inode_permission(inode, MAY_WRITE); -+ error = inode_permission2(mnt, inode, MAY_WRITE); - if (error) - goto mnt_drop_write_and_out; - -@@ -360,6 +360,7 @@ long do_faccessat(int dfd, const char __user *filename, int mode) - struct cred *override_cred; - struct path path; - struct inode *inode; -+ struct vfsmount *mnt; - int res; - unsigned int lookup_flags = LOOKUP_FOLLOW; - -@@ -409,6 +410,7 @@ long do_faccessat(int dfd, const char __user *filename, int mode) - goto out; - - inode = d_backing_inode(path.dentry); -+ mnt = path.mnt; - - if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { - /* -@@ -420,7 +422,7 @@ long do_faccessat(int dfd, const char __user *filename, int mode) - goto out_path_release; - } - -- res = inode_permission(inode, mode | MAY_ACCESS); -+ res = inode_permission2(mnt, inode, mode | MAY_ACCESS); - /* SuS v2 requires we report a read only fs too */ - if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) - goto out_path_release; -@@ -469,7 +471,7 @@ int ksys_chdir(const char __user *filename) - if (error) - goto out; - -- error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); -+ error = inode_permission2(path.mnt, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); - if (error) - goto dput_and_out; - -@@ -503,7 +505,8 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd) - if (!d_can_lookup(f.file->f_path.dentry)) - goto out_putf; - -- error = inode_permission(file_inode(f.file), MAY_EXEC | MAY_CHDIR); -+ error = inode_permission2(f.file->f_path.mnt, file_inode(f.file), -+ MAY_EXEC | MAY_CHDIR); - if (!error) - set_fs_pwd(current->fs, &f.file->f_path); - out_putf: -@@ -522,7 +525,7 @@ int ksys_chroot(const char __user *filename) - if (error) - goto out; - -- error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); -+ error = inode_permission2(path.mnt, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); - if (error) - goto dput_and_out; - -diff --git a/fs/xattr.c b/fs/xattr.c -index 90dd78f0eb27..142fa44fa587 100644 ---- a/fs/xattr.c -+++ b/fs/xattr.c -@@ -131,7 +131,7 @@ xattr_permission(struct inode *inode, const char *name, int mask) - return -EPERM; - } - -- return inode_permission(inode, mask); -+ return inode_permission2(ERR_PTR(-EOPNOTSUPP), inode, mask); - } - - int -diff --git a/include/linux/fs.h b/include/linux/fs.h -index 35e662198dc5..42c2cfc33ce7 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1709,13 +1709,21 @@ extern bool inode_owner_or_capable(const struct inode *inode); - * VFS helper functions.. - */ - extern int vfs_create(struct inode *, struct dentry *, umode_t, bool); -+extern int vfs_create2(struct vfsmount *, struct inode *, struct dentry *, umode_t, bool); - extern int vfs_mkdir(struct inode *, struct dentry *, umode_t); -+extern int vfs_mkdir2(struct vfsmount *, struct inode *, struct dentry *, umode_t); - extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); -+extern int vfs_mknod2(struct vfsmount *, struct inode *, struct dentry *, umode_t, dev_t); - extern int vfs_symlink(struct inode *, struct dentry *, const char *); -+extern int vfs_symlink2(struct vfsmount *, struct inode *, struct dentry *, const char *); - extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); -+extern int vfs_link2(struct vfsmount *, struct dentry *, struct inode *, struct dentry *, struct inode **); - extern int vfs_rmdir(struct inode *, struct dentry *); -+extern int vfs_rmdir2(struct vfsmount *, struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); -+extern int vfs_unlink2(struct vfsmount *, struct inode *, struct dentry *, struct inode **); - extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int); -+extern int vfs_rename2(struct vfsmount *, struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int); - extern int vfs_whiteout(struct inode *, struct dentry *); - - extern struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, -@@ -1724,6 +1732,9 @@ extern struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, - int vfs_mkobj(struct dentry *, umode_t, - int (*f)(struct dentry *, umode_t, void *), - void *); -+int vfs_mkobj2(struct vfsmount *, struct dentry *, umode_t, -+ int (*f)(struct dentry *, umode_t, void *), -+ void *); - - extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); - -@@ -1857,6 +1868,7 @@ struct inode_operations { - struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); - const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); - int (*permission) (struct inode *, int); -+ int (*permission2) (struct vfsmount *, struct inode *, int); - struct posix_acl * (*get_acl)(struct inode *, int); - - int (*readlink) (struct dentry *, char __user *,int); -@@ -2871,6 +2883,7 @@ extern sector_t bmap(struct inode *, sector_t); - extern int notify_change(struct dentry *, struct iattr *, struct inode **); - extern int notify_change2(struct vfsmount *, struct dentry *, struct iattr *, struct inode **); - extern int inode_permission(struct inode *, int); -+extern int inode_permission2(struct vfsmount *, struct inode *, int); - extern int generic_permission(struct inode *, int); - extern int __check_sticky(struct inode *dir, struct inode *inode); - -diff --git a/include/linux/namei.h b/include/linux/namei.h -index 397a08ade6a2..cb288d62f1d6 100644 ---- a/include/linux/namei.h -+++ b/include/linux/namei.h -@@ -59,6 +59,7 @@ extern int kern_path_mountpoint(int, const char *, struct path *, unsigned int); - - extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int); - extern struct dentry *lookup_one_len(const char *, struct dentry *, int); -+extern struct dentry *lookup_one_len2(const char *, struct vfsmount *mnt, struct dentry *, int); - extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int); - - extern int follow_down_one(struct path *); -diff --git a/ipc/mqueue.c b/ipc/mqueue.c -index 3d920ff15c80..948d116f3446 100644 ---- a/ipc/mqueue.c -+++ b/ipc/mqueue.c -@@ -768,7 +768,7 @@ static void remove_notification(struct mqueue_inode_info *info) - info->notify_user_ns = NULL; - } - --static int prepare_open(struct dentry *dentry, int oflag, int ro, -+static int prepare_open(struct vfsmount *mnt, struct dentry *dentry, int oflag, int ro, - umode_t mode, struct filename *name, - struct mq_attr *attr) - { -@@ -782,7 +782,7 @@ static int prepare_open(struct dentry *dentry, int oflag, int ro, - if (ro) - return ro; - audit_inode_parent_hidden(name, dentry->d_parent); -- return vfs_mkobj(dentry, mode & ~current_umask(), -+ return vfs_mkobj2(mnt, dentry, mode & ~current_umask(), - mqueue_create_attr, attr); - } - /* it already existed */ -@@ -792,7 +792,7 @@ static int prepare_open(struct dentry *dentry, int oflag, int ro, - if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) - return -EINVAL; - acc = oflag2acc[oflag & O_ACCMODE]; -- return inode_permission(d_inode(dentry), acc); -+ return inode_permission2(mnt, d_inode(dentry), acc); - } - - static int do_mq_open(const char __user *u_name, int oflag, umode_t mode, -@@ -816,13 +816,13 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode, - - ro = mnt_want_write(mnt); /* we'll drop it in any case */ - inode_lock(d_inode(root)); -- path.dentry = lookup_one_len(name->name, root, strlen(name->name)); -+ path.dentry = lookup_one_len2(name->name, mnt, root, strlen(name->name)); - if (IS_ERR(path.dentry)) { - error = PTR_ERR(path.dentry); - goto out_putfd; - } - path.mnt = mntget(mnt); -- error = prepare_open(path.dentry, oflag, ro, mode, name, attr); -+ error = prepare_open(path.mnt, path.dentry, oflag, ro, mode, name, attr); - if (!error) { - struct file *file = dentry_open(&path, oflag, current_cred()); - if (!IS_ERR(file)) -@@ -872,7 +872,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) - if (err) - goto out_name; - inode_lock_nested(d_inode(mnt->mnt_root), I_MUTEX_PARENT); -- dentry = lookup_one_len(name->name, mnt->mnt_root, -+ dentry = lookup_one_len2(name->name, mnt, mnt->mnt_root, - strlen(name->name)); - if (IS_ERR(dentry)) { - err = PTR_ERR(dentry); -@@ -884,7 +884,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) - err = -ENOENT; - } else { - ihold(inode); -- err = vfs_unlink(d_inode(dentry->d_parent), dentry, NULL); -+ err = vfs_unlink2(mnt, d_inode(dentry->d_parent), dentry, NULL); - } - dput(dentry); - -diff --git a/security/inode.c b/security/inode.c -index 6c326939750d..289504656ea9 100644 ---- a/security/inode.c -+++ b/security/inode.c -@@ -128,7 +128,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, - dir = d_inode(parent); - - inode_lock(dir); -- dentry = lookup_one_len(name, parent, strlen(name)); -+ dentry = lookup_one_len2(name, mount, parent, strlen(name)); - if (IS_ERR(dentry)) - goto out; - diff --git a/patches/ANDROID-vfs-Add-setattr2-for-filesystems-with-per-mount-permissions.patch b/patches/ANDROID-vfs-Add-setattr2-for-filesystems-with-per-mount-permissions.patch deleted file mode 100644 index 2debdac527208b184894be390f90bf287dc822ba..0000000000000000000000000000000000000000 --- a/patches/ANDROID-vfs-Add-setattr2-for-filesystems-with-per-mount-permissions.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Wed, 26 Oct 2016 16:33:11 -0700 -Subject: ANDROID: vfs: Add setattr2 for filesystems with per mount permissions - -This allows filesystems to use their mount private data to -influence the permssions they use in setattr2. It has -been separated into a new call to avoid disrupting current -setattr users. - -Test: HiKey/X15 + Pie + android-mainline, - and HiKey + AOSP Maser + android-mainline, - directories under /sdcard created, - output of mount is right, - CTS test collecting device infor works - -Change-Id: I19959038309284448f1b7f232d579674ef546385 -Signed-off-by: Daniel Rosenberg -Signed-off-by: Yongqin Liu ---- - fs/attr.c | 12 ++++++++++-- - fs/coredump.c | 2 +- - fs/inode.c | 6 +++--- - fs/namei.c | 2 +- - fs/open.c | 23 ++++++++++++++++------- - fs/utimes.c | 2 +- - include/linux/fs.h | 6 +++++- - 7 files changed, 37 insertions(+), 16 deletions(-) - -diff --git a/fs/attr.c b/fs/attr.c -index df28035aa23e..0a7f9d67bb35 100644 ---- a/fs/attr.c -+++ b/fs/attr.c -@@ -226,7 +226,7 @@ EXPORT_SYMBOL(setattr_copy); - * the file open for write, as there can be no conflicting delegation in - * that case. - */ --int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode) -+int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode) - { - struct inode *inode = dentry->d_inode; - umode_t mode = inode->i_mode; -@@ -333,7 +333,9 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de - if (error) - return error; - -- if (inode->i_op->setattr) -+ if (mnt && inode->i_op->setattr2) -+ error = inode->i_op->setattr2(mnt, dentry, attr); -+ else if (inode->i_op->setattr) - error = inode->i_op->setattr(dentry, attr); - else - error = simple_setattr(dentry, attr); -@@ -346,4 +348,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de - - return error; - } -+EXPORT_SYMBOL(notify_change2); -+ -+int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode) -+{ -+ return notify_change2(NULL, dentry, attr, delegated_inode); -+} - EXPORT_SYMBOL(notify_change); -diff --git a/fs/coredump.c b/fs/coredump.c -index b1ea7dfbd149..a6b542bb4d85 100644 ---- a/fs/coredump.c -+++ b/fs/coredump.c -@@ -775,7 +775,7 @@ void do_coredump(const kernel_siginfo_t *siginfo) - goto close_fail; - if (!(cprm.file->f_mode & FMODE_CAN_WRITE)) - goto close_fail; -- if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file)) -+ if (do_truncate2(cprm.file->f_path.mnt, cprm.file->f_path.dentry, 0, 0, cprm.file)) - goto close_fail; - } - -diff --git a/fs/inode.c b/fs/inode.c -index fef457a42882..853ce7aa6301 100644 ---- a/fs/inode.c -+++ b/fs/inode.c -@@ -1810,7 +1810,7 @@ int dentry_needs_remove_privs(struct dentry *dentry) - return mask; - } - --static int __remove_privs(struct dentry *dentry, int kill) -+static int __remove_privs(struct vfsmount *mnt, struct dentry *dentry, int kill) - { - struct iattr newattrs; - -@@ -1819,7 +1819,7 @@ static int __remove_privs(struct dentry *dentry, int kill) - * Note we call this on write, so notify_change will not - * encounter any conflicting delegations: - */ -- return notify_change(dentry, &newattrs, NULL); -+ return notify_change2(mnt, dentry, &newattrs, NULL); - } - - /* -@@ -1846,7 +1846,7 @@ int file_remove_privs(struct file *file) - if (kill < 0) - return kill; - if (kill) -- error = __remove_privs(dentry, kill); -+ error = __remove_privs(file->f_path.mnt, dentry, kill); - if (!error) - inode_has_no_xattr(inode); - -diff --git a/fs/namei.c b/fs/namei.c -index 671c3c1a3425..8a77269e644f 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -2995,7 +2995,7 @@ static int handle_truncate(struct file *filp) - if (!error) - error = security_path_truncate(path); - if (!error) { -- error = do_truncate(path->dentry, 0, -+ error = do_truncate2(path->mnt, path->dentry, 0, - ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, - filp); - } -diff --git a/fs/open.c b/fs/open.c -index b62f5c0923a8..a189284464a0 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -35,8 +35,8 @@ - - #include "internal.h" - --int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, -- struct file *filp) -+int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length, -+ unsigned int time_attrs, struct file *filp) - { - int ret; - struct iattr newattrs; -@@ -61,17 +61,24 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, - - inode_lock(dentry->d_inode); - /* Note any delegations or leases have already been broken: */ -- ret = notify_change(dentry, &newattrs, NULL); -+ ret = notify_change2(mnt, dentry, &newattrs, NULL); - inode_unlock(dentry->d_inode); - return ret; - } -+int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, -+ struct file *filp) -+{ -+ return do_truncate2(NULL, dentry, length, time_attrs, filp); -+} - - long vfs_truncate(const struct path *path, loff_t length) - { - struct inode *inode; -+ struct vfsmount *mnt; - long error; - - inode = path->dentry->d_inode; -+ mnt = path->mnt; - - /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ - if (S_ISDIR(inode->i_mode)) -@@ -107,7 +114,7 @@ long vfs_truncate(const struct path *path, loff_t length) - if (!error) - error = security_path_truncate(path); - if (!error) -- error = do_truncate(path->dentry, length, 0, NULL); -+ error = do_truncate2(mnt, path->dentry, length, 0, NULL); - - put_write_and_out: - put_write_access(inode); -@@ -156,6 +163,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small) - { - struct inode *inode; - struct dentry *dentry; -+ struct vfsmount *mnt; - struct fd f; - int error; - -@@ -172,6 +180,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small) - small = 0; - - dentry = f.file->f_path.dentry; -+ mnt = f.file->f_path.mnt; - inode = dentry->d_inode; - error = -EINVAL; - if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE)) -@@ -192,7 +201,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small) - if (!error) - error = security_path_truncate(&f.file->f_path); - if (!error) -- error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, f.file); -+ error = do_truncate2(mnt, dentry, length, ATTR_MTIME|ATTR_CTIME, f.file); - sb_end_write(inode->i_sb); - out_putf: - fdput(f); -@@ -558,7 +567,7 @@ static int chmod_common(const struct path *path, umode_t mode) - goto out_unlock; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(path->dentry, &newattrs, &delegated_inode); -+ error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode); - out_unlock: - inode_unlock(inode); - if (delegated_inode) { -@@ -649,7 +658,7 @@ static int chown_common(const struct path *path, uid_t user, gid_t group) - inode_lock(inode); - error = security_path_chown(path, uid, gid); - if (!error) -- error = notify_change(path->dentry, &newattrs, &delegated_inode); -+ error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode); - inode_unlock(inode); - if (delegated_inode) { - error = break_deleg_wait(&delegated_inode); -diff --git a/fs/utimes.c b/fs/utimes.c -index 1ba3f7883870..93a3a58a4f6d 100644 ---- a/fs/utimes.c -+++ b/fs/utimes.c -@@ -57,7 +57,7 @@ static int utimes_common(const struct path *path, struct timespec64 *times) - } - retry_deleg: - inode_lock(inode); -- error = notify_change(path->dentry, &newattrs, &delegated_inode); -+ error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode); - inode_unlock(inode); - if (delegated_inode) { - error = break_deleg_wait(&delegated_inode); -diff --git a/include/linux/fs.h b/include/linux/fs.h -index e0d909d35763..35e662198dc5 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1871,7 +1871,8 @@ struct inode_operations { - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *, unsigned int); - int (*setattr) (struct dentry *, struct iattr *); -- int (*getattr) (const struct path *, struct kstat *, u32, unsigned int); -+ int (*setattr2) (struct vfsmount *, struct dentry *, struct iattr *); -+ int (*getattr) (const struct path *, struct kstat *, u32, unsigned int); - ssize_t (*listxattr) (struct dentry *, char *, size_t); - int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, - u64 len); -@@ -2519,6 +2520,8 @@ static_assert(offsetof(struct filename, iname) % sizeof(long) == 0); - extern long vfs_truncate(const struct path *, loff_t); - extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, - struct file *filp); -+extern int do_truncate2(struct vfsmount *, struct dentry *, loff_t start, -+ unsigned int time_attrs, struct file *filp); - extern int vfs_fallocate(struct file *file, int mode, loff_t offset, - loff_t len); - extern long do_sys_open(int dfd, const char __user *filename, int flags, -@@ -2866,6 +2869,7 @@ extern void emergency_remount(void); - extern sector_t bmap(struct inode *, sector_t); - #endif - extern int notify_change(struct dentry *, struct iattr *, struct inode **); -+extern int notify_change2(struct vfsmount *, struct dentry *, struct iattr *, struct inode **); - extern int inode_permission(struct inode *, int); - extern int generic_permission(struct inode *, int); - extern int __check_sticky(struct inode *dir, struct inode *inode); diff --git a/patches/ANDROID-vfs-add-d_canonical_path-for-stacked-filesystem-support.patch b/patches/ANDROID-vfs-add-d_canonical_path-for-stacked-filesystem-support.patch deleted file mode 100644 index 0b763c77f5b179f51ff8f98fe10e2b82d937dc6f..0000000000000000000000000000000000000000 --- a/patches/ANDROID-vfs-add-d_canonical_path-for-stacked-filesystem-support.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Daniel Rosenberg -Date: Thu, 11 Feb 2016 16:44:15 -0800 -Subject: ANDROID: vfs: add d_canonical_path for stacked filesystem support - -Inotify does not currently know when a filesystem -is acting as a wrapper around another fs. This means -that inotify watchers will miss any modifications to -the base file, as well as any made in a separate -stacked fs that points to the same file. -d_canonical_path solves this problem by allowing the fs -to map a dentry to a path in the lower fs. Inotify -can use it to find the appropriate place to watch to -be informed of all changes to a file. - -Test: HiKey/X15 + Pie + android-mainline, - and HiKey + AOSP Maser + android-mainline, - directories under /sdcard created, - output of mount is right, - CTS test collecting device infor works - -Bug: 70706497 -Change-Id: I09563baffad1711a045e45c1bd0bd8713c2cc0b6 -Signed-off-by: Daniel Rosenberg -[astrachan: Folded 34df4102216e ("ANDROID: fsnotify: Notify lower fs of - open") into this patch] -Signed-off-by: Alistair Strachan -Signed-off-by: Yongqin Liu ---- - fs/notify/inotify/inotify_user.c | 15 +++++++++++++-- - include/linux/dcache.h | 1 + - include/linux/fsnotify.h | 7 +++++++ - 3 files changed, 21 insertions(+), 2 deletions(-) - -diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c -index 3e66e6c8f53a..bd16ec03b5fd 100644 ---- a/fs/notify/inotify/inotify_user.c -+++ b/fs/notify/inotify/inotify_user.c -@@ -701,6 +701,8 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, - struct fsnotify_group *group; - struct inode *inode; - struct path path; -+ struct path alteredpath; -+ struct path *canonical_path = &path; - struct fd f; - int ret; - unsigned flags = 0; -@@ -747,13 +749,22 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, - if (ret) - goto fput_and_out; - -+ /* support stacked filesystems */ -+ if(path.dentry && path.dentry->d_op) { -+ if (path.dentry->d_op->d_canonical_path) { -+ path.dentry->d_op->d_canonical_path(&path, &alteredpath); -+ canonical_path = &alteredpath; -+ path_put(&path); -+ } -+ } -+ - /* inode held in place by reference to path; group by fget on fd */ -- inode = path.dentry->d_inode; -+ inode = canonical_path->dentry->d_inode; - group = f.file->private_data; - - /* create/update an inode mark */ - ret = inotify_update_watch(group, inode, mask); -- path_put(&path); -+ path_put(canonical_path); - fput_and_out: - fdput(f); - return ret; -diff --git a/include/linux/dcache.h b/include/linux/dcache.h -index 10090f11ab95..d59a73cdb10e 100644 ---- a/include/linux/dcache.h -+++ b/include/linux/dcache.h -@@ -147,6 +147,7 @@ struct dentry_operations { - struct vfsmount *(*d_automount)(struct path *); - int (*d_manage)(const struct path *, bool); - struct dentry *(*d_real)(struct dentry *, const struct inode *); -+ void (*d_canonical_path)(const struct path *, struct path *); - } ____cacheline_aligned; - - /* -diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h -index a2d5d175d3c1..e018872b047c 100644 ---- a/include/linux/fsnotify.h -+++ b/include/linux/fsnotify.h -@@ -262,6 +262,7 @@ static inline void fsnotify_modify(struct file *file) - static inline void fsnotify_open(struct file *file) - { - const struct path *path = &file->f_path; -+ struct path lower_path; - struct inode *inode = file_inode(file); - __u32 mask = FS_OPEN; - -@@ -270,6 +271,12 @@ static inline void fsnotify_open(struct file *file) - if (file->f_flags & __FMODE_EXEC) - mask |= FS_OPEN_EXEC; - -+ if (path->dentry->d_op && path->dentry->d_op->d_canonical_path) { -+ path->dentry->d_op->d_canonical_path(path, &lower_path); -+ fsnotify_parent(&lower_path, NULL, mask); -+ fsnotify(lower_path.dentry->d_inode, mask, &lower_path, FSNOTIFY_EVENT_PATH, NULL, 0); -+ path_put(&lower_path); -+ } - fsnotify_path(inode, path, mask); - } - diff --git a/patches/ANDROID-x86-Remove-a-useless-warning-message.patch b/patches/ANDROID-x86-Remove-a-useless-warning-message.patch deleted file mode 100644 index d2c837d7f9d28bfd223d1d0ed6b69f97e5fdf1f9..0000000000000000000000000000000000000000 --- a/patches/ANDROID-x86-Remove-a-useless-warning-message.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alistair Strachan -Date: Mon, 29 Oct 2018 15:20:05 -0700 -Subject: ANDROID: x86: Remove a useless warning message - -While we wait for a clang prebuilt with asm-goto support, we have -removed the kbuild's detection of a clang without asm-goto (the -kernel builds fine without it), so we don't need to see the same -warning about not having the compiler feature fill the kernel build -log, which potentially hides other issues. - -This patch should be reverted when the new clang prebuilt lands and -we have reverted the other reverts. - -Bug: 120440614 -Test: make ARCH=x86_64 x86_64_cuttlefish_defconfig && make ARCH=x86_64 -Change-Id: I26aee5b9dd291f27b950dee4b0c64471d972ddb5 -Signed-off-by: Alistair Strachan ---- - arch/x86/include/asm/cpufeature.h | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h -index 59bf91c57aa8..48670eb3b4d7 100644 ---- a/arch/x86/include/asm/cpufeature.h -+++ b/arch/x86/include/asm/cpufeature.h -@@ -154,9 +154,6 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit); - * Workaround for the sake of BPF compilation which utilizes kernel - * headers, but clang does not support ASM GOTO and fails the build. - */ --#ifndef __BPF_TRACING__ --#warning "Compiler lacks ASM_GOTO support. Add -D __BPF_TRACING__ to your compiler arguments" --#endif - - #define static_cpu_has(bit) boot_cpu_has(bit) - diff --git a/patches/ANDROID-x86-gki_defconfig-enable-DMA_CMA.patch b/patches/ANDROID-x86-gki_defconfig-enable-DMA_CMA.patch deleted file mode 100644 index efdaf3f503eb273a36c196fa878d91b37497636d..0000000000000000000000000000000000000000 --- a/patches/ANDROID-x86-gki_defconfig-enable-DMA_CMA.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ram Muthiah -Date: Wed, 12 Jun 2019 17:17:06 -0700 -Subject: ANDROID: x86 gki_defconfig: enable DMA_CMA - -Test: Boot x86 gki -Change-Id: Ic517f4de7865b9bb3f20fbd282a97dd7d8fa775e -Signed-off-by: Ram Muthiah ---- - arch/x86/configs/gki_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig -index 94690e9d016a..7f4edee2b52d 100644 ---- a/arch/x86/configs/gki_defconfig -+++ b/arch/x86/configs/gki_defconfig -@@ -321,6 +321,7 @@ CONFIG_CRYPTO_ANSI_CPRNG=y - CONFIG_CRYPTO_DEV_VIRTIO=y - CONFIG_CRC8=y - CONFIG_XZ_DEC=y -+CONFIG_DMA_CMA=y - CONFIG_PRINTK_TIME=y - CONFIG_DEBUG_INFO=y - # CONFIG_ENABLE_MUST_CHECK is not set diff --git a/patches/ANDROID-xfrm-remove-in_compat_syscall-checks.patch b/patches/ANDROID-xfrm-remove-in_compat_syscall-checks.patch deleted file mode 100644 index 37ef2493360e498396b08dba311b5b38b7e83dcc..0000000000000000000000000000000000000000 --- a/patches/ANDROID-xfrm-remove-in_compat_syscall-checks.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tri Vo -Date: Thu, 25 Jul 2019 16:57:16 -0700 -Subject: ANDROID: xfrm: remove in_compat_syscall() checks - -This hack is needed to run 32-bit userspace on 64-bit kernel. - -Bug: 138147164 -Test: kernel_net_tests -Signed-off-by: Tri Vo -Change-Id: I083d32b45ca985cfadfe3ce57d253b63202befde ---- - net/xfrm/xfrm_state.c | 3 --- - net/xfrm/xfrm_user.c | 3 --- - 2 files changed, 6 deletions(-) - -diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c -index c6f3c4a1bd99..c023b27c70e1 100644 ---- a/net/xfrm/xfrm_state.c -+++ b/net/xfrm/xfrm_state.c -@@ -2266,9 +2266,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen - struct xfrm_mgr *km; - struct xfrm_policy *pol = NULL; - -- if (in_compat_syscall()) -- return -EOPNOTSUPP; -- - if (!optval && !optlen) { - xfrm_sk_policy_insert(sk, XFRM_POLICY_IN, NULL); - xfrm_sk_policy_insert(sk, XFRM_POLICY_OUT, NULL); -diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c -index b88ba45ff1ac..ed6e6790b3e7 100644 ---- a/net/xfrm/xfrm_user.c -+++ b/net/xfrm/xfrm_user.c -@@ -2634,9 +2634,6 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, - const struct xfrm_link *link; - int type, err; - -- if (in_compat_syscall()) -- return -EOPNOTSUPP; -- - type = nlh->nlmsg_type; - if (type > XFRM_MSG_MAX) - return -EINVAL; diff --git a/patches/FROMGIT-driver-core-Add-fwnode_to_dev-to-look-up-device-from-fwnode.patch b/patches/FROMGIT-driver-core-Add-fwnode_to_dev-to-look-up-device-from-fwnode.patch deleted file mode 100644 index 217740268a819eac4a2150fdbdea78af5a8d1251..0000000000000000000000000000000000000000 --- a/patches/FROMGIT-driver-core-Add-fwnode_to_dev-to-look-up-device-from-fwnode.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Saravana Kannan -Date: Wed, 4 Sep 2019 14:11:20 -0700 -Subject: FROMGIT: driver core: Add fwnode_to_dev() to look up device from - fwnode - -It's often useful to look up a device that corresponds to a fwnode. So -add an API to do that irrespective of the bus on which the device has -been added to. - -Signed-off-by: Saravana Kannan -Link: https://lore.kernel.org/r/20190904211126.47518-2-saravanak@google.com -Signed-off-by: Greg Kroah-Hartman - -(cherry-picked from commit 372a67c0c5ef63f55bd1eb480d9555328d8ec0f2 - https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) - -Bug: 141703324 -Change-Id: I68c36177da083bfb04e73c1b754e740f40faf284 ---- - drivers/base/core.c | 7 +++++++ - include/linux/fwnode.h | 2 ++ - 2 files changed, 9 insertions(+) - -diff --git a/drivers/base/core.c b/drivers/base/core.c -index 2db62d98e395..510fabf8918c 100644 ---- a/drivers/base/core.c -+++ b/drivers/base/core.c -@@ -2198,6 +2198,10 @@ int device_add(struct device *dev) - BUS_NOTIFY_ADD_DEVICE, dev); - - kobject_uevent(&dev->kobj, KOBJ_ADD); -+ -+ if (dev->fwnode && !dev->fwnode->dev) -+ dev->fwnode->dev = dev; -+ - bus_probe_device(dev); - if (parent) - klist_add_tail(&dev->p->knode_parent, -@@ -2342,6 +2346,9 @@ void device_del(struct device *dev) - kill_device(dev); - device_unlock(dev); - -+ if (dev->fwnode && dev->fwnode->dev == dev) -+ dev->fwnode->dev = NULL; -+ - /* Notify clients of device removal. This call must come - * before dpm_sysfs_remove(). - */ -diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h -index ababd6bc82f3..d8c6d231d577 100644 ---- a/include/linux/fwnode.h -+++ b/include/linux/fwnode.h -@@ -17,6 +17,7 @@ struct device; - struct fwnode_handle { - struct fwnode_handle *secondary; - const struct fwnode_operations *ops; -+ struct device *dev; - }; - - /** -@@ -123,5 +124,6 @@ struct fwnode_operations { - if (fwnode_has_op(fwnode, op)) \ - (fwnode)->ops->op(fwnode, ## __VA_ARGS__); \ - } while (false) -+#define get_dev_from_fwnode(fwnode) get_device((fwnode)->dev) - - #endif diff --git a/patches/FROMGIT-driver-core-Add-support-for-linking-devices-during-device-addition.patch b/patches/FROMGIT-driver-core-Add-support-for-linking-devices-during-device-addition.patch deleted file mode 100644 index 05de50e179dca33006918775f6dd73fdb3e7e36f..0000000000000000000000000000000000000000 --- a/patches/FROMGIT-driver-core-Add-support-for-linking-devices-during-device-addition.patch +++ /dev/null @@ -1,240 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Saravana Kannan -Date: Wed, 4 Sep 2019 14:11:21 -0700 -Subject: FROMGIT: driver core: Add support for linking devices during device - addition - -The firmware corresponding to a device (dev.fwnode) might be able to -provide functional dependency information between a device and its -supplier and consumer devices. Tracking this functional dependency -allows optimizing device probe order and informing a supplier when all -its consumers have probed (and thereby actively managing their -resources). - -The existing device links feature allows tracking and using -supplier-consumer relationships. So, this patch adds the add_links() -fwnode callback to allow firmware to create device links for each -device as the device is added. - -However, when consumer devices are added, they might not have a supplier -device to link to despite needing mandatory resources/functionality from -one or more suppliers. A waiting_for_suppliers list is created to track -such consumers and retry linking them when new devices get added. - -Signed-off-by: Saravana Kannan -Link: https://lore.kernel.org/r/20190904211126.47518-3-saravanak@google.com -Signed-off-by: Greg Kroah-Hartman - -(cherry-picked from commit e2ae9bcc4aaacda04edb75c4eea93384719efaa5 - https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) - -Bug: 141703324 -Change-Id: I97ffa57fa71588bf198e78d8b5a313b860b17bf5 ---- - Documentation/driver-api/device_link.rst | 3 +- - drivers/base/core.c | 88 ++++++++++++++++++++++++ - include/linux/device.h | 2 + - include/linux/fwnode.h | 17 +++++ - 4 files changed, 109 insertions(+), 1 deletion(-) - -diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst -index 1b5020ec6517..bc2d89af88ce 100644 ---- a/Documentation/driver-api/device_link.rst -+++ b/Documentation/driver-api/device_link.rst -@@ -281,7 +281,8 @@ State machine - :c:func:`driver_bound()`.) - - * Before a consumer device is probed, presence of supplier drivers is -- verified by checking that links to suppliers are in ``DL_STATE_AVAILABLE`` -+ verified by checking the consumer device is not in the wait_for_suppliers -+ list and by checking that links to suppliers are in ``DL_STATE_AVAILABLE`` - state. The state of the links is updated to ``DL_STATE_CONSUMER_PROBE``. - (Call to :c:func:`device_links_check_suppliers()` from - :c:func:`really_probe()`.) -diff --git a/drivers/base/core.c b/drivers/base/core.c -index 510fabf8918c..b3896da73b3d 100644 ---- a/drivers/base/core.c -+++ b/drivers/base/core.c -@@ -44,6 +44,8 @@ early_param("sysfs.deprecated", sysfs_deprecated_setup); - #endif - - /* Device links support. */ -+static LIST_HEAD(wait_for_suppliers); -+static DEFINE_MUTEX(wfs_lock); - - #ifdef CONFIG_SRCU - static DEFINE_MUTEX(device_links_lock); -@@ -430,6 +432,58 @@ struct device_link *device_link_add(struct device *consumer, - } - EXPORT_SYMBOL_GPL(device_link_add); - -+/** -+ * device_link_wait_for_supplier - Add device to wait_for_suppliers list -+ * @consumer: Consumer device -+ * -+ * Marks the @consumer device as waiting for suppliers to become available by -+ * adding it to the wait_for_suppliers list. The consumer device will never be -+ * probed until it's removed from the wait_for_suppliers list. -+ * -+ * The caller is responsible for adding the links to the supplier devices once -+ * they are available and removing the @consumer device from the -+ * wait_for_suppliers list once links to all the suppliers have been created. -+ * -+ * This function is NOT meant to be called from the probe function of the -+ * consumer but rather from code that creates/adds the consumer device. -+ */ -+static void device_link_wait_for_supplier(struct device *consumer) -+{ -+ mutex_lock(&wfs_lock); -+ list_add_tail(&consumer->links.needs_suppliers, &wait_for_suppliers); -+ mutex_unlock(&wfs_lock); -+} -+ -+/** -+ * device_link_add_missing_supplier_links - Add links from consumer devices to -+ * supplier devices, leaving any -+ * consumer with inactive suppliers on -+ * the wait_for_suppliers list -+ * -+ * Loops through all consumers waiting on suppliers and tries to add all their -+ * supplier links. If that succeeds, the consumer device is removed from -+ * wait_for_suppliers list. Otherwise, they are left in the wait_for_suppliers -+ * list. Devices left on the wait_for_suppliers list will not be probed. -+ * -+ * The fwnode add_links callback is expected to return 0 if it has found and -+ * added all the supplier links for the consumer device. It should return an -+ * error if it isn't able to do so. -+ * -+ * The caller of device_link_wait_for_supplier() is expected to call this once -+ * it's aware of potential suppliers becoming available. -+ */ -+static void device_link_add_missing_supplier_links(void) -+{ -+ struct device *dev, *tmp; -+ -+ mutex_lock(&wfs_lock); -+ list_for_each_entry_safe(dev, tmp, &wait_for_suppliers, -+ links.needs_suppliers) -+ if (!fwnode_call_int_op(dev->fwnode, add_links, dev)) -+ list_del_init(&dev->links.needs_suppliers); -+ mutex_unlock(&wfs_lock); -+} -+ - static void device_link_free(struct device_link *link) - { - while (refcount_dec_not_one(&link->rpm_active)) -@@ -564,6 +618,17 @@ int device_links_check_suppliers(struct device *dev) - struct device_link *link; - int ret = 0; - -+ /* -+ * Device waiting for supplier to become available is not allowed to -+ * probe. -+ */ -+ mutex_lock(&wfs_lock); -+ if (!list_empty(&dev->links.needs_suppliers)) { -+ mutex_unlock(&wfs_lock); -+ return -EPROBE_DEFER; -+ } -+ mutex_unlock(&wfs_lock); -+ - device_links_write_lock(); - - list_for_each_entry(link, &dev->links.suppliers, c_node) { -@@ -848,6 +913,10 @@ static void device_links_purge(struct device *dev) - { - struct device_link *link, *ln; - -+ mutex_lock(&wfs_lock); -+ list_del(&dev->links.needs_suppliers); -+ mutex_unlock(&wfs_lock); -+ - /* - * Delete all of the remaining links from this device to any other - * devices (either consumers or suppliers). -@@ -1712,6 +1781,7 @@ void device_initialize(struct device *dev) - #endif - INIT_LIST_HEAD(&dev->links.consumers); - INIT_LIST_HEAD(&dev->links.suppliers); -+ INIT_LIST_HEAD(&dev->links.needs_suppliers); - dev->links.status = DL_DEV_NO_DRIVER; - } - EXPORT_SYMBOL_GPL(device_initialize); -@@ -2202,6 +2272,24 @@ int device_add(struct device *dev) - if (dev->fwnode && !dev->fwnode->dev) - dev->fwnode->dev = dev; - -+ /* -+ * Check if any of the other devices (consumers) have been waiting for -+ * this device (supplier) to be added so that they can create a device -+ * link to it. -+ * -+ * This needs to happen after device_pm_add() because device_link_add() -+ * requires the supplier be registered before it's called. -+ * -+ * But this also needs to happe before bus_probe_device() to make sure -+ * waiting consumers can link to it before the driver is bound to the -+ * device and the driver sync_state callback is called for this device. -+ */ -+ device_link_add_missing_supplier_links(); -+ -+ if (fwnode_has_op(dev->fwnode, add_links) -+ && fwnode_call_int_op(dev->fwnode, add_links, dev)) -+ device_link_wait_for_supplier(dev); -+ - bus_probe_device(dev); - if (parent) - klist_add_tail(&dev->p->knode_parent, -diff --git a/include/linux/device.h b/include/linux/device.h -index 297239a08bb7..c6fb5b3431b7 100644 ---- a/include/linux/device.h -+++ b/include/linux/device.h -@@ -1135,11 +1135,13 @@ enum dl_dev_state { - * struct dev_links_info - Device data related to device links. - * @suppliers: List of links to supplier devices. - * @consumers: List of links to consumer devices. -+ * @needs_suppliers: Hook to global list of devices waiting for suppliers. - * @status: Driver status information. - */ - struct dev_links_info { - struct list_head suppliers; - struct list_head consumers; -+ struct list_head needs_suppliers; - enum dl_dev_state status; - }; - -diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h -index d8c6d231d577..6ae05b9ce359 100644 ---- a/include/linux/fwnode.h -+++ b/include/linux/fwnode.h -@@ -66,6 +66,21 @@ struct fwnode_reference_args { - * endpoint node. - * @graph_get_port_parent: Return the parent node of a port node. - * @graph_parse_endpoint: Parse endpoint for port and endpoint id. -+ * @add_links: Called after the device corresponding to the fwnode is added -+ * using device_add(). The function is expected to create device -+ * links to all the suppliers of the device that are available at -+ * the time this function is called. The function must NOT stop -+ * at the first failed device link if other unlinked supplier -+ * devices are present in the system. If some suppliers are not -+ * yet available, this function will be called again when other -+ * devices are added to allow creating device links to any newly -+ * available suppliers. -+ * -+ * Return 0 if device links have been successfully created to all -+ * the suppliers of this device or if the supplier information is -+ * not known. Return an error if and only if the supplier -+ * information is known but some of the suppliers are not yet -+ * available to create device links to. - */ - struct fwnode_operations { - struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); -@@ -103,6 +118,8 @@ struct fwnode_operations { - (*graph_get_port_parent)(struct fwnode_handle *fwnode); - int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode, - struct fwnode_endpoint *endpoint); -+ int (*add_links)(const struct fwnode_handle *fwnode, -+ struct device *dev); - }; - - #define fwnode_has_op(fwnode, op) \ diff --git a/patches/FROMGIT-driver-core-Add-sync_state-driver-bus-callback.patch b/patches/FROMGIT-driver-core-Add-sync_state-driver-bus-callback.patch deleted file mode 100644 index 5e5297a560117cc3180223543e4a3f7ffde108ba..0000000000000000000000000000000000000000 --- a/patches/FROMGIT-driver-core-Add-sync_state-driver-bus-callback.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Saravana Kannan -Date: Wed, 4 Sep 2019 14:11:23 -0700 -Subject: FROMGIT: driver core: Add sync_state driver/bus callback - -This sync_state driver/bus callback is called once all the consumers -of a supplier have probed successfully. - -This allows the supplier device's driver/bus to sync the supplier -device's state to the software state with the guarantee that all the -consumers are actively managing the resources provided by the supplier -device. - -To maintain backwards compatibility and ease transition from existing -frameworks and resource cleanup schemes, late_initcall_sync is the -earliest when the sync_state callback might be called. - -There is no upper bound on the time by which the sync_state callback -has to be called. This is because if a consumer device never probes, -the supplier has to maintain its resources in the state left by the -bootloader. For example, if the bootloader leaves the display -backlight at a fixed voltage and the backlight driver is never probed, -you don't want the backlight to ever be turned off after boot up. - -Also, when multiple devices are added after kernel init, some -suppliers could be added before their consumer devices get added. In -these instances, the supplier devices could get their sync_state -callback called right after they probe because the consumers devices -haven't had a chance to create device links to the suppliers. - -To handle this correctly, this change also provides APIs to -pause/resume sync state callbacks so that when multiple devices are -added, their sync_state callback evaluation can be postponed to happen -after all of them are added. - -kbuild test robot reported missing documentation for device.state_synced -Reported-by: kbuild test robot -Signed-off-by: Saravana Kannan -Link: https://lore.kernel.org/r/20190904211126.47518-5-saravanak@google.com -Signed-off-by: Greg Kroah-Hartman - -(cherry-picked from commit fc5a251d0fd7ca9038bab78a8c97932c8c6ca23b - https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) - -Bug: 141703324 -Change-Id: I3e0a483c76d6ae3e5fe5aa6b3df65d0417c65ebb ---- - drivers/base/core.c | 72 ++++++++++++++++++++++++++++++++++++++++++ - include/linux/device.h | 24 ++++++++++++++ - 2 files changed, 96 insertions(+) - -diff --git a/drivers/base/core.c b/drivers/base/core.c -index b3896da73b3d..acbf0b1414ab 100644 ---- a/drivers/base/core.c -+++ b/drivers/base/core.c -@@ -46,6 +46,8 @@ early_param("sysfs.deprecated", sysfs_deprecated_setup); - /* Device links support. */ - static LIST_HEAD(wait_for_suppliers); - static DEFINE_MUTEX(wfs_lock); -+static LIST_HEAD(deferred_sync); -+static unsigned int defer_sync_state_count = 1; - - #ifdef CONFIG_SRCU - static DEFINE_MUTEX(device_links_lock); -@@ -648,6 +650,69 @@ int device_links_check_suppliers(struct device *dev) - return ret; - } - -+static void __device_links_supplier_sync_state(struct device *dev) -+{ -+ struct device_link *link; -+ -+ if (dev->state_synced) -+ return; -+ -+ list_for_each_entry(link, &dev->links.consumers, s_node) { -+ if (!(link->flags & DL_FLAG_MANAGED)) -+ continue; -+ if (link->status != DL_STATE_ACTIVE) -+ return; -+ } -+ -+ if (dev->bus->sync_state) -+ dev->bus->sync_state(dev); -+ else if (dev->driver && dev->driver->sync_state) -+ dev->driver->sync_state(dev); -+ -+ dev->state_synced = true; -+} -+ -+void device_links_supplier_sync_state_pause(void) -+{ -+ device_links_write_lock(); -+ defer_sync_state_count++; -+ device_links_write_unlock(); -+} -+ -+void device_links_supplier_sync_state_resume(void) -+{ -+ struct device *dev, *tmp; -+ -+ device_links_write_lock(); -+ if (!defer_sync_state_count) { -+ WARN(true, "Unmatched sync_state pause/resume!"); -+ goto out; -+ } -+ defer_sync_state_count--; -+ if (defer_sync_state_count) -+ goto out; -+ -+ list_for_each_entry_safe(dev, tmp, &deferred_sync, links.defer_sync) { -+ __device_links_supplier_sync_state(dev); -+ list_del_init(&dev->links.defer_sync); -+ } -+out: -+ device_links_write_unlock(); -+} -+ -+static int sync_state_resume_initcall(void) -+{ -+ device_links_supplier_sync_state_resume(); -+ return 0; -+} -+late_initcall(sync_state_resume_initcall); -+ -+static void __device_links_supplier_defer_sync(struct device *sup) -+{ -+ if (list_empty(&sup->links.defer_sync)) -+ list_add_tail(&sup->links.defer_sync, &deferred_sync); -+} -+ - /** - * device_links_driver_bound - Update device links after probing its driver. - * @dev: Device to update the links for. -@@ -692,6 +757,11 @@ void device_links_driver_bound(struct device *dev) - - WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); - WRITE_ONCE(link->status, DL_STATE_ACTIVE); -+ -+ if (defer_sync_state_count) -+ __device_links_supplier_defer_sync(link->supplier); -+ else -+ __device_links_supplier_sync_state(link->supplier); - } - - dev->links.status = DL_DEV_DRIVER_BOUND; -@@ -808,6 +878,7 @@ void device_links_driver_cleanup(struct device *dev) - WRITE_ONCE(link->status, DL_STATE_DORMANT); - } - -+ list_del_init(&dev->links.defer_sync); - __device_links_no_driver(dev); - - device_links_write_unlock(); -@@ -1782,6 +1853,7 @@ void device_initialize(struct device *dev) - INIT_LIST_HEAD(&dev->links.consumers); - INIT_LIST_HEAD(&dev->links.suppliers); - INIT_LIST_HEAD(&dev->links.needs_suppliers); -+ INIT_LIST_HEAD(&dev->links.defer_sync); - dev->links.status = DL_DEV_NO_DRIVER; - } - EXPORT_SYMBOL_GPL(device_initialize); -diff --git a/include/linux/device.h b/include/linux/device.h -index c6fb5b3431b7..6978bb471567 100644 ---- a/include/linux/device.h -+++ b/include/linux/device.h -@@ -80,6 +80,13 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); - * that generate uevents to add the environment variables. - * @probe: Called when a new device or driver add to this bus, and callback - * the specific driver's probe to initial the matched device. -+ * @sync_state: Called to sync device state to software state after all the -+ * state tracking consumers linked to this device (present at -+ * the time of late_initcall) have successfully bound to a -+ * driver. If the device has no consumers, this function will -+ * be called at late_initcall_sync level. If the device has -+ * consumers that are never bound to a driver, this function -+ * will never get called until they do. - * @remove: Called when a device removed from this bus. - * @shutdown: Called at shut-down time to quiesce the device. - * -@@ -123,6 +130,7 @@ struct bus_type { - int (*match)(struct device *dev, struct device_driver *drv); - int (*uevent)(struct device *dev, struct kobj_uevent_env *env); - int (*probe)(struct device *dev); -+ void (*sync_state)(struct device *dev); - int (*remove)(struct device *dev); - void (*shutdown)(struct device *dev); - -@@ -340,6 +348,13 @@ enum probe_type { - * @probe: Called to query the existence of a specific device, - * whether this driver can work with it, and bind the driver - * to a specific device. -+ * @sync_state: Called to sync device state to software state after all the -+ * state tracking consumers linked to this device (present at -+ * the time of late_initcall) have successfully bound to a -+ * driver. If the device has no consumers, this function will -+ * be called at late_initcall_sync level. If the device has -+ * consumers that are never bound to a driver, this function -+ * will never get called until they do. - * @remove: Called when the device is removed from the system to - * unbind a device from this driver. - * @shutdown: Called at shut-down time to quiesce the device. -@@ -379,6 +394,7 @@ struct device_driver { - const struct acpi_device_id *acpi_match_table; - - int (*probe) (struct device *dev); -+ void (*sync_state)(struct device *dev); - int (*remove) (struct device *dev); - void (*shutdown) (struct device *dev); - int (*suspend) (struct device *dev, pm_message_t state); -@@ -1136,12 +1152,14 @@ enum dl_dev_state { - * @suppliers: List of links to supplier devices. - * @consumers: List of links to consumer devices. - * @needs_suppliers: Hook to global list of devices waiting for suppliers. -+ * @defer_sync: Hook to global list of devices that have deferred sync_state. - * @status: Driver status information. - */ - struct dev_links_info { - struct list_head suppliers; - struct list_head consumers; - struct list_head needs_suppliers; -+ struct list_head defer_sync; - enum dl_dev_state status; - }; - -@@ -1217,6 +1235,9 @@ struct dev_links_info { - * @offline: Set after successful invocation of bus type's .offline(). - * @of_node_reused: Set if the device-tree node is shared with an ancestor - * device. -+ * @state_synced: The hardware state of this device has been synced to match -+ * the software state of this device by calling the driver/bus -+ * sync_state() callback. - * @dma_coherent: this particular device is dma coherent, even if the - * architecture supports non-coherent devices. - * -@@ -1313,6 +1334,7 @@ struct device { - bool offline_disabled:1; - bool offline:1; - bool of_node_reused:1; -+ bool state_synced:1; - #if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \ - defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL) -@@ -1655,6 +1677,8 @@ struct device_link *device_link_add(struct device *consumer, - struct device *supplier, u32 flags); - void device_link_del(struct device_link *link); - void device_link_remove(void *consumer, struct device *supplier); -+void device_links_supplier_sync_state_pause(void); -+void device_links_supplier_sync_state_resume(void); - - #ifndef dev_fmt - #define dev_fmt(fmt) fmt diff --git a/patches/FROMGIT-of-platform-Pause-resume-sync-state-during-init-and-of_platform_populate.patch b/patches/FROMGIT-of-platform-Pause-resume-sync-state-during-init-and-of_platform_populate.patch deleted file mode 100644 index cabfdfe2b84bbf2c1782ba94b6578d74d5e64411..0000000000000000000000000000000000000000 --- a/patches/FROMGIT-of-platform-Pause-resume-sync-state-during-init-and-of_platform_populate.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Saravana Kannan -Date: Wed, 4 Sep 2019 14:11:24 -0700 -Subject: FROMGIT: of/platform: Pause/resume sync state during init and - of_platform_populate() - -When all the top level devices are populated from DT during kernel -init, the supplier devices could be added and probed before the -consumer devices are added and linked to the suppliers. To avoid the -sync_state() callback from being called prematurely, pause the -sync_state() callbacks before populating the devices and resume them -at late_initcall_sync(). - -Similarly, when children devices are populated from a module using -of_platform_populate(), there could be supplier-consumer dependencies -between the children devices that are populated. To avoid the same -problem with sync_state() being called prematurely, pause and resume -sync_state() callbacks across of_platform_populate(). - -Signed-off-by: Saravana Kannan -Link: https://lore.kernel.org/r/20190904211126.47518-6-saravanak@google.com -Signed-off-by: Greg Kroah-Hartman - -(cherry-picked from commit 5e6669387e2287f25f09fd0abd279dae104cfa7e - https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) - -Bug: 141703324 -Change-Id: Ia43ebbc9071d4d6a59b347ccae99fcf0ab192269 ---- - drivers/of/platform.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/drivers/of/platform.c b/drivers/of/platform.c -index b47a2292fe8e..d93891a05f60 100644 ---- a/drivers/of/platform.c -+++ b/drivers/of/platform.c -@@ -480,6 +480,7 @@ int of_platform_populate(struct device_node *root, - pr_debug("%s()\n", __func__); - pr_debug(" starting at: %pOF\n", root); - -+ device_links_supplier_sync_state_pause(); - for_each_child_of_node(root, child) { - rc = of_platform_bus_create(child, matches, lookup, parent, true); - if (rc) { -@@ -487,6 +488,8 @@ int of_platform_populate(struct device_node *root, - break; - } - } -+ device_links_supplier_sync_state_resume(); -+ - of_node_set_flag(root, OF_POPULATED_BUS); - - of_node_put(root); -@@ -518,6 +521,7 @@ static int __init of_platform_default_populate_init(void) - if (!of_have_populated_dt()) - return -ENODEV; - -+ device_links_supplier_sync_state_pause(); - /* - * Handle certain compatibles explicitly, since we don't want to create - * platform_devices for every node in /reserved-memory with a -@@ -538,6 +542,14 @@ static int __init of_platform_default_populate_init(void) - return 0; - } - arch_initcall_sync(of_platform_default_populate_init); -+ -+static int __init of_platform_sync_state_init(void) -+{ -+ if (of_have_populated_dt()) -+ device_links_supplier_sync_state_resume(); -+ return 0; -+} -+late_initcall_sync(of_platform_sync_state_init); - #endif - - int of_platform_device_destroy(struct device *dev, void *data) diff --git a/patches/FROMGIT-of-property-Add-functional-dependency-link-from-DT-bindings.patch b/patches/FROMGIT-of-property-Add-functional-dependency-link-from-DT-bindings.patch deleted file mode 100644 index 036ccfde126baa025b00f7f6edbfc4497e5030c1..0000000000000000000000000000000000000000 --- a/patches/FROMGIT-of-property-Add-functional-dependency-link-from-DT-bindings.patch +++ /dev/null @@ -1,362 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Saravana Kannan -Date: Wed, 4 Sep 2019 14:11:22 -0700 -Subject: FROMGIT: of: property: Add functional dependency link from DT - bindings - -Add device links after the devices are created (but before they are -probed) by looking at common DT bindings like clocks and -interconnects. - -Automatically adding device links for functional dependencies at the -framework level provides the following benefits: - -- Optimizes device probe order and avoids the useless work of - attempting probes of devices that will not probe successfully - (because their suppliers aren't present or haven't probed yet). - - For example, in a commonly available mobile SoC, registering just - one consumer device's driver at an initcall level earlier than the - supplier device's driver causes 11 failed probe attempts before the - consumer device probes successfully. This was with a kernel with all - the drivers statically compiled in. This problem gets a lot worse if - all the drivers are loaded as modules without direct symbol - dependencies. - -- Supplier devices like clock providers, interconnect providers, etc - need to keep the resources they provide active and at a particular - state(s) during boot up even if their current set of consumers don't - request the resource to be active. This is because the rest of the - consumers might not have probed yet and turning off the resource - before all the consumers have probed could lead to a hang or - undesired user experience. - - Some frameworks (Eg: regulator) handle this today by turning off - "unused" resources at late_initcall_sync and hoping all the devices - have probed by then. This is not a valid assumption for systems with - loadable modules. Other frameworks (Eg: clock) just don't handle - this due to the lack of a clear signal for when they can turn off - resources. This leads to downstream hacks to handle cases like this - that can easily be solved in the upstream kernel. - - By linking devices before they are probed, we give suppliers a clear - count of the number of dependent consumers. Once all of the - consumers are active, the suppliers can turn off the unused - resources without making assumptions about the number of consumers. - -By default we just add device-links to track "driver presence" (probe -succeeded) of the supplier device. If any other functionality provided -by device-links are needed, it is left to the consumer/supplier -devices to change the link when they probe. - -kbuild test robot reported clang error about missing const -Reported-by: kbuild test robot -Signed-off-by: Saravana Kannan -Link: https://lore.kernel.org/r/20190904211126.47518-4-saravanak@google.com -Signed-off-by: Greg Kroah-Hartman - -(cherry-picked from commit a3e1d1a7f5fcccaf1d252278425fea9a4a553100 - https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) - -Bug: 141703324 -Change-Id: I54a2dc3c4e91e418bcf1895c16bb8658dcfe1bee ---- - .../admin-guide/kernel-parameters.rst | 1 + - .../admin-guide/kernel-parameters.txt | 6 + - drivers/of/property.c | 241 ++++++++++++++++++ - 3 files changed, 248 insertions(+) - -diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst -index d05d531b4ec9..6d421694d98e 100644 ---- a/Documentation/admin-guide/kernel-parameters.rst -+++ b/Documentation/admin-guide/kernel-parameters.rst -@@ -127,6 +127,7 @@ parameter is applicable:: - NET Appropriate network support is enabled. - NUMA NUMA support is enabled. - NFS Appropriate NFS support is enabled. -+ OF Devicetree is enabled. - OSS OSS sound support is enabled. - PV_OPS A paravirtualized kernel is enabled. - PARIDE The ParIDE (parallel port IDE) subsystem is enabled. -diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt -index a84a83f8881e..dc727fa8c831 100644 ---- a/Documentation/admin-guide/kernel-parameters.txt -+++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -3194,6 +3194,12 @@ - This can be set from sysctl after boot. - See Documentation/admin-guide/sysctl/vm.rst for details. - -+ of_devlink [OF, KNL] Create device links between consumer and -+ supplier devices by scanning the devictree to infer the -+ consumer/supplier relationships. A consumer device -+ will not be probed until all the supplier devices have -+ probed successfully. -+ - ohci1394_dma=early [HW] enable debugging via the ohci1394 driver. - See Documentation/debugging-via-ohci1394.txt for more - info. -diff --git a/drivers/of/property.c b/drivers/of/property.c -index d7fa75e31f22..23b5ee5b0570 100644 ---- a/drivers/of/property.c -+++ b/drivers/of/property.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include "of_private.h" - -@@ -985,6 +986,245 @@ of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode, - return of_device_get_match_data(dev); - } - -+static bool of_is_ancestor_of(struct device_node *test_ancestor, -+ struct device_node *child) -+{ -+ of_node_get(child); -+ while (child) { -+ if (child == test_ancestor) { -+ of_node_put(child); -+ return false; -+ } -+ child = of_get_next_parent(child); -+ } -+ return true; -+} -+ -+/** -+ * of_link_to_phandle - Add device link to supplier from supplier phandle -+ * @dev: consumer device -+ * @sup_np: phandle to supplier device tree node -+ * -+ * Given a phandle to a supplier device tree node (@sup_np), this function -+ * finds the device that owns the supplier device tree node and creates a -+ * device link from @dev consumer device to the supplier device. This function -+ * doesn't create device links for invalid scenarios such as trying to create a -+ * link with a parent device as the consumer of its child device. In such -+ * cases, it returns an error. -+ * -+ * Returns: -+ * - 0 if link successfully created to supplier -+ * - -EAGAIN if linking to the supplier should be reattempted -+ * - -EINVAL if the supplier link is invalid and should not be created -+ * - -ENODEV if there is no device that corresponds to the supplier phandle -+ */ -+static int of_link_to_phandle(struct device *dev, struct device_node *sup_np) -+{ -+ struct device *sup_dev; -+ u32 dl_flags = DL_FLAG_AUTOPROBE_CONSUMER; -+ int ret = 0; -+ struct device_node *tmp_np = sup_np; -+ -+ of_node_get(sup_np); -+ /* -+ * Find the device node that contains the supplier phandle. It may be -+ * @sup_np or it may be an ancestor of @sup_np. -+ */ -+ while (sup_np && !of_find_property(sup_np, "compatible", NULL)) -+ sup_np = of_get_next_parent(sup_np); -+ if (!sup_np) { -+ dev_dbg(dev, "Not linking to %pOFP - No device\n", tmp_np); -+ return -ENODEV; -+ } -+ -+ /* -+ * Don't allow linking a device node as a consumer of one of its -+ * descendant nodes. By definition, a child node can't be a functional -+ * dependency for the parent node. -+ */ -+ if (!of_is_ancestor_of(dev->of_node, sup_np)) { -+ dev_dbg(dev, "Not linking to %pOFP - is descendant\n", sup_np); -+ of_node_put(sup_np); -+ return -EINVAL; -+ } -+ sup_dev = get_dev_from_fwnode(&sup_np->fwnode); -+ of_node_put(sup_np); -+ if (!sup_dev) -+ return -EAGAIN; -+ if (!device_link_add(dev, sup_dev, dl_flags)) -+ ret = -EAGAIN; -+ put_device(sup_dev); -+ return ret; -+} -+ -+/** -+ * parse_prop_cells - Property parsing function for suppliers -+ * -+ * @np: Pointer to device tree node containing a list -+ * @prop_name: Name of property to be parsed. Expected to hold phandle values -+ * @index: For properties holding a list of phandles, this is the index -+ * into the list. -+ * @list_name: Property name that is known to contain list of phandle(s) to -+ * supplier(s) -+ * @cells_name: property name that specifies phandles' arguments count -+ * -+ * This is a helper function to parse properties that have a known fixed name -+ * and are a list of phandles and phandle arguments. -+ * -+ * Returns: -+ * - phandle node pointer with refcount incremented. Caller must of_node_put() -+ * on it when done. -+ * - NULL if no phandle found at index -+ */ -+static struct device_node *parse_prop_cells(struct device_node *np, -+ const char *prop_name, int index, -+ const char *list_name, -+ const char *cells_name) -+{ -+ struct of_phandle_args sup_args; -+ -+ if (strcmp(prop_name, list_name)) -+ return NULL; -+ -+ if (of_parse_phandle_with_args(np, list_name, cells_name, index, -+ &sup_args)) -+ return NULL; -+ -+ return sup_args.np; -+} -+ -+static struct device_node *parse_clocks(struct device_node *np, -+ const char *prop_name, int index) -+{ -+ return parse_prop_cells(np, prop_name, index, "clocks", "#clock-cells"); -+} -+ -+static struct device_node *parse_interconnects(struct device_node *np, -+ const char *prop_name, int index) -+{ -+ return parse_prop_cells(np, prop_name, index, "interconnects", -+ "#interconnect-cells"); -+} -+ -+static int strcmp_suffix(const char *str, const char *suffix) -+{ -+ unsigned int len, suffix_len; -+ -+ len = strlen(str); -+ suffix_len = strlen(suffix); -+ if (len <= suffix_len) -+ return -1; -+ return strcmp(str + len - suffix_len, suffix); -+} -+ -+static struct device_node *parse_regulators(struct device_node *np, -+ const char *prop_name, int index) -+{ -+ if (index || strcmp_suffix(prop_name, "-supply")) -+ return NULL; -+ -+ return of_parse_phandle(np, prop_name, 0); -+} -+ -+/** -+ * struct supplier_bindings - Property parsing functions for suppliers -+ * -+ * @parse_prop: function name -+ * parse_prop() finds the node corresponding to a supplier phandle -+ * @parse_prop.np: Pointer to device node holding supplier phandle property -+ * @parse_prop.prop_name: Name of property holding a phandle value -+ * @parse_prop.index: For properties holding a list of phandles, this is the -+ * index into the list -+ * -+ * Returns: -+ * parse_prop() return values are -+ * - phandle node pointer with refcount incremented. Caller must of_node_put() -+ * on it when done. -+ * - NULL if no phandle found at index -+ */ -+struct supplier_bindings { -+ struct device_node *(*parse_prop)(struct device_node *np, -+ const char *prop_name, int index); -+}; -+ -+static const struct supplier_bindings bindings[] = { -+ { .parse_prop = parse_clocks, }, -+ { .parse_prop = parse_interconnects, }, -+ { .parse_prop = parse_regulators, }, -+ {}, -+}; -+ -+/** -+ * of_link_property - Create device links to suppliers listed in a property -+ * @dev: Consumer device -+ * @con_np: The consumer device tree node which contains the property -+ * @prop_name: Name of property to be parsed -+ * -+ * This function checks if the property @prop_name that is present in the -+ * @con_np device tree node is one of the known common device tree bindings -+ * that list phandles to suppliers. If @prop_name isn't one, this function -+ * doesn't do anything. -+ * -+ * If @prop_name is one, this function attempts to create device links from the -+ * consumer device @dev to all the devices of the suppliers listed in -+ * @prop_name. -+ * -+ * Any failed attempt to create a device link will NOT result in an immediate -+ * return. of_link_property() must create links to all the available supplier -+ * devices even when attempts to create a link to one or more suppliers fail. -+ */ -+static int of_link_property(struct device *dev, struct device_node *con_np, -+ const char *prop_name) -+{ -+ struct device_node *phandle; -+ const struct supplier_bindings *s = bindings; -+ unsigned int i = 0; -+ bool matched = false; -+ int ret = 0; -+ -+ /* Do not stop at first failed link, link all available suppliers. */ -+ while (!matched && s->parse_prop) { -+ while ((phandle = s->parse_prop(con_np, prop_name, i))) { -+ matched = true; -+ i++; -+ if (of_link_to_phandle(dev, phandle) == -EAGAIN) -+ ret = -EAGAIN; -+ of_node_put(phandle); -+ } -+ s++; -+ } -+ return ret; -+} -+ -+static int __of_link_to_suppliers(struct device *dev, -+ struct device_node *con_np) -+{ -+ struct device_node *child; -+ struct property *p; -+ int ret = 0; -+ -+ for_each_property_of_node(con_np, p) -+ if (of_link_property(dev, con_np, p->name)) -+ ret = -EAGAIN; -+ -+ return ret; -+} -+ -+static bool of_devlink; -+core_param(of_devlink, of_devlink, bool, 0); -+ -+static int of_fwnode_add_links(const struct fwnode_handle *fwnode, -+ struct device *dev) -+{ -+ if (!of_devlink) -+ return 0; -+ -+ if (unlikely(!is_of_node(fwnode))) -+ return 0; -+ -+ return __of_link_to_suppliers(dev, to_of_node(fwnode)); -+} -+ - const struct fwnode_operations of_fwnode_ops = { - .get = of_fwnode_get, - .put = of_fwnode_put, -@@ -1001,5 +1241,6 @@ const struct fwnode_operations of_fwnode_ops = { - .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint, - .graph_get_port_parent = of_fwnode_graph_get_port_parent, - .graph_parse_endpoint = of_fwnode_graph_parse_endpoint, -+ .add_links = of_fwnode_add_links, - }; - EXPORT_SYMBOL_GPL(of_fwnode_ops); diff --git a/patches/FROMGIT-of-property-Create-device-links-for-all-child-supplier-depencencies.patch b/patches/FROMGIT-of-property-Create-device-links-for-all-child-supplier-depencencies.patch deleted file mode 100644 index ba97c8f0d2c91b4e14dadc39f103f063c53c11cc..0000000000000000000000000000000000000000 --- a/patches/FROMGIT-of-property-Create-device-links-for-all-child-supplier-depencencies.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Saravana Kannan -Date: Wed, 4 Sep 2019 14:11:25 -0700 -Subject: FROMGIT: of: property: Create device links for all child-supplier - depencencies - -A parent device can have child devices that it adds when it probes. But -this probing of the parent device can happen way after kernel init is done --- for example, when the parent device's driver is loaded as a module. - -In such cases, if the child devices depend on a supplier in the system, we -need to make sure the supplier gets the sync_state() callback only after -these child devices are added and probed. - -To achieve this, when creating device links for a device by looking at its -DT node, don't just look at DT references at the top node level. Look at DT -references in all the descendant nodes too and create device links from the -ancestor device to all these supplier devices. - -This way, when the parent device probes and adds child devices, the child -devices can then create their own device links to the suppliers and further -delay the supplier's sync_state() callback to after the child devices are -probed. - -Example: -In this illustration, -> denotes DT references and indentation -represents child status. - -Device node A - Device node B -> D - Device node C -> B, D - -Device node D - -Assume all these devices have their drivers loaded as modules. - -Without this patch, this is the sequence of events: -1. D is added. -2. A is added. -3. Device D probes. -4. Device D gets its sync_state() callback. -5. Device B and C might malfunction because their resources got - altered/turned off before they can make active requests for them. - -With this patch, this is the sequence of events: -1. D is added. -2. A is added and creates device links to D. -3. Device link from A to B is not added because A is a parent of B. -4. Device D probes. -5. Device D does not get it's sync_state() callback because consumer A - hasn't probed yet. -5. Device A probes. -5. a. Devices B and C are added. -5. b. Device links from B and C to D are added. -5. c. Device A's probe completes. -6. Device D does not get it's sync_state() callback because consumer A - has probed but consumers B and C haven't probed yet. -7. Device B and C probe. -8. Device D gets it's sync_state() callback because all its consumers - have probed. -9. None of the devices malfunction. - -Signed-off-by: Saravana Kannan -Link: https://lore.kernel.org/r/20190904211126.47518-7-saravanak@google.com -Signed-off-by: Greg Kroah-Hartman - -(cherry-picked from commit d4387cd117414ba80230f27a514be5ca4a09cfcc - https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-next) - -Fixes: 141703324 -Change-Id: I38186d6cc4671bd8747dae8c440b09717a487088 ---- - drivers/of/property.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/of/property.c b/drivers/of/property.c -index 23b5ee5b0570..923d6f88a99c 100644 ---- a/drivers/of/property.c -+++ b/drivers/of/property.c -@@ -1207,6 +1207,10 @@ static int __of_link_to_suppliers(struct device *dev, - if (of_link_property(dev, con_np, p->name)) - ret = -EAGAIN; - -+ for_each_child_of_node(con_np, child) -+ if (__of_link_to_suppliers(dev, child)) -+ ret = -EAGAIN; -+ - return ret; - } - diff --git a/patches/UPSTREAM-base-soc-Handle-custom-soc-information-sysfs-entries.patch b/patches/UPSTREAM-base-soc-Handle-custom-soc-information-sysfs-entries.patch deleted file mode 100644 index 7e81da9a0c9c5c18c566e9f3a4332f6f3ff7943a..0000000000000000000000000000000000000000 --- a/patches/UPSTREAM-base-soc-Handle-custom-soc-information-sysfs-entries.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Murali Nalajala -Date: Mon, 7 Oct 2019 13:37:42 -0700 -Subject: UPSTREAM: base: soc: Handle custom soc information sysfs entries - -Soc framework exposed sysfs entries are not sufficient for some -of the h/w platforms. Currently there is no interface where soc -drivers can expose further information about their SoCs via soc -framework. This change address this limitation where clients can -pass their custom entries as attribute group and soc framework -would expose them as sysfs properties. - -Bug: 141190076 -Signed-off-by: Murali Nalajala -Reviewed-by: Bjorn Andersson -Reviewed-by: Stephen Boyd -Link: https://lore.kernel.org/r/1570480662-25252-1-git-send-email-mnalajal@codeaurora.org -Signed-off-by: Greg Kroah-Hartman -(cherry-picked from c31e73121f4c1ec45a3e523ac6ce3ce6dafdcec1) -Signed-off-by: Greg Kroah-Hartman -Change-Id: Ia1c8d697e29052b4503da7c4b30c2c97d3b697f7 ---- - drivers/base/soc.c | 30 +++++++++++++++++------------- - include/linux/sys_soc.h | 1 + - 2 files changed, 18 insertions(+), 13 deletions(-) - -diff --git a/drivers/base/soc.c b/drivers/base/soc.c -index 7c0c5ca5953d..4af11a423475 100644 ---- a/drivers/base/soc.c -+++ b/drivers/base/soc.c -@@ -104,15 +104,12 @@ static const struct attribute_group soc_attr_group = { - .is_visible = soc_attribute_mode, - }; - --static const struct attribute_group *soc_attr_groups[] = { -- &soc_attr_group, -- NULL, --}; -- - static void soc_release(struct device *dev) - { - struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); - -+ ida_simple_remove(&soc_ida, soc_dev->soc_dev_num); -+ kfree(soc_dev->dev.groups); - kfree(soc_dev); - } - -@@ -121,6 +118,7 @@ static struct soc_device_attribute *early_soc_dev_attr; - struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr) - { - struct soc_device *soc_dev; -+ const struct attribute_group **soc_attr_groups; - int ret; - - if (!soc_bus_type.p) { -@@ -136,10 +134,18 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr - goto out1; - } - -+ soc_attr_groups = kcalloc(3, sizeof(*soc_attr_groups), GFP_KERNEL); -+ if (!soc_attr_groups) { -+ ret = -ENOMEM; -+ goto out2; -+ } -+ soc_attr_groups[0] = &soc_attr_group; -+ soc_attr_groups[1] = soc_dev_attr->custom_attr_group; -+ - /* Fetch a unique (reclaimable) SOC ID. */ - ret = ida_simple_get(&soc_ida, 0, 0, GFP_KERNEL); - if (ret < 0) -- goto out2; -+ goto out3; - soc_dev->soc_dev_num = ret; - - soc_dev->attr = soc_dev_attr; -@@ -150,15 +156,15 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr - dev_set_name(&soc_dev->dev, "soc%d", soc_dev->soc_dev_num); - - ret = device_register(&soc_dev->dev); -- if (ret) -- goto out3; -+ if (ret) { -+ put_device(&soc_dev->dev); -+ return ERR_PTR(ret); -+ } - - return soc_dev; - - out3: -- ida_simple_remove(&soc_ida, soc_dev->soc_dev_num); -- put_device(&soc_dev->dev); -- soc_dev = NULL; -+ kfree(soc_attr_groups); - out2: - kfree(soc_dev); - out1: -@@ -169,8 +175,6 @@ EXPORT_SYMBOL_GPL(soc_device_register); - /* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */ - void soc_device_unregister(struct soc_device *soc_dev) - { -- ida_simple_remove(&soc_ida, soc_dev->soc_dev_num); -- - device_unregister(&soc_dev->dev); - early_soc_dev_attr = NULL; - } -diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h -index 48ceea867dd6..d9b3cf0f410c 100644 ---- a/include/linux/sys_soc.h -+++ b/include/linux/sys_soc.h -@@ -15,6 +15,7 @@ struct soc_device_attribute { - const char *serial_number; - const char *soc_id; - const void *data; -+ const struct attribute_group *custom_attr_group; - }; - - /** diff --git a/patches/series b/patches/series deleted file mode 100644 index 372638712df3f0556366f7bce0ebf13fa2a72b8d..0000000000000000000000000000000000000000 --- a/patches/series +++ /dev/null @@ -1,197 +0,0 @@ -# -# android-mainline patches -# -# Applies onto mainline 4f5cafb5cb84 Linux v5.4-rc3 -# Matches android-mainline 06dc94f19d2f "ANDROID: sched: Honor sync flag for energy-aware wakeups" -# -ANDROID-x86-Remove-a-useless-warning-message.patch -ANDROID-Kbuild-LLVMLinux-allow-overriding-clang-target-triple.patch -ANDROID-net-xfrm-make-PF_KEY-SHA256-use-RFC-compliant-truncation.patch -ANDROID-arm64-copy-CONFIG_CMDLINE_EXTEND-from-ARM.patch -ANDROID-of-Support-CONFIG_CMDLINE_EXTEND-config-option.patch -ANDROID-fs-epoll-use-freezable-blocking-call.patch -ANDROID-mm-add-a-field-to-store-names-for-private-anonymous-memory.patch -ANDROID-usb-gadget-configfs-Add-usb_function-ptr-to-fi-struct.patch -ANDROID-usb-gadget-configfs-Add-Uevent-to-notify-userspace.patch -ANDROID-usb-gadget-configfs-Add-function-devices-to-the-parent.patch -ANDROID-usb-gadget-configfs-Add-state-attribute-to-android_device.patch -ANDROID-usb-gadget-configfs-Add-device-attribute-to-determine-gadget-state.patch -ANDROID-usb-gadget-f_accessory-Add-Android-Accessory-function.patch -ANDROID-usb-gadget-f_midi-create-F_midi-device.patch -ANDROID-usb-gadget-f_midi-set-fi-f-to-NULL-when-free-f_midi-function.patch -ANDROID-usb-gadget-f_audio_source-New-gadget-driver-for-audio-output.patch -ANDROID-mmc-core-Add-ignore-mmc-pm-notify-functionality.patch -ANDROID-uid_cputime-Adds-accounting-for-the-cputimes-per-uid.patch -ANDROID-uid_cputime-add-per-uid-IO-usage-accounting.patch -ANDROID-taskstats-track-fsync-syscalls.patch -ANDROID-AVB-error-handler-to-invalidate-vbmeta-partition.patch -ANDROID-fs-FS-tracepoints-to-track-IO.patch -ANDROID-cpu-send-KOBJ_ONLINE-event-when-enabling-cpus.patch -ANDROID-add-extra-free-kbytes-tunable.patch -ANDROID-power-wakeup_reason-add-an-API-to-log-wakeup-reasons.patch -ANDROID-netfilter-xt_quota2-adding-the-original-quota2-from-xtables-addons.patch -ANDROID-netfilter-xt_IDLETIMER-Add-new-netlink-msg-type.patch -ANDROID-security-perf-Allow-further-restriction-of-perf_event_open.patch -ANDROID-net-ipv6-autoconf-routes-into-per-device-tables.patch -ANDROID-binder-add-support-for-RT-prio-inheritance.patch -ANDROID-cpufreq-track-per-task-time-in-state.patch -ANDROID-cpufreq-times-track-per-uid-time-in-state.patch -ANDROID-proc-Add-proc-uid-directory.patch -ANDROID-cpufreq-Add-time_in_state-to-proc-uid-directories.patch -ANDROID-cpufreq-times-add-proc-uid_concurrent_-active-policy-_time.patch -ANDROID-cpufreq-times-record-fast-switch-frequency-transitions.patch -ANDROID-cpufreq-times-optimize-proc-files.patch -ANDROID-dm-bow-Add-dm-bow-feature.patch -ANDROID-dm-bow-Fix-32-bit-compile-errors.patch -ANDROID-cpufreq-times-don-t-copy-invalid-freqs-from-freq-table.patch -ANDROID-gki_defconfig-initial-config-based-on-cuttlefish_defconfig.patch -ANDROID-gki_defconfig-Remove-recommended-configs-not-present-on-b1c1.patch -ANDROID-gki_defconfig-Remove-cuttlefish-specific-configs.patch -ANDROID-gki_defconfig-common-configs-for-device-DLKMs.patch -ANDROID-Expose-gki_defconfig-to-build.config.patch -ANDROID-Move-from-clang-r349610-to-r353983c.patch -ANDROID-gki_defconfig-disable-CONFIG_LCD_CLASS_DEVICE-module.patch -ANDROID-gki_defconfig-sync-with-savedefconfig.patch -ANDROID-gki_defconfig-remove-more-recommended-configs.patch -ANDROID-gki_defconfig-more-generic-configs-for-DLKMs.patch -ANDROID-sync-defconfigs-with-savedefconfig.patch -ANDROID-Four-part-revert-of-asm-goto-usage-1-4.patch -ANDROID-Four-part-revert-of-asm-goto-usage-2-4.patch -ANDROID-Four-part-revert-of-asm-goto-usage-3-4.patch -ANDROID-Four-part-revert-of-asm-goto-usage-4-4.patch -ANDROID-Removed-check-for-asm-goto.patch -ANDROID-Add-initial-x86_64-gki_defconfig.patch -ANDROID-added-configs-so-that-GKI-boots-on-x86-cuttlefish.patch -ANDROID-gki_defconfig-enable-CMA-and-increase-CMA_AREAS.patch -ANDROID-gki_defconfig-enable-SLAB_FREELIST_RANDOM-SLAB_FREELIST_HARDENED.patch -ANDROID-gki_defconfig-Enable-CMA-SLAB_FREELIST-RANDOM-and-HARDENED-on-x86.patch -ANDROID-gki_defconfig-enable-DMA_CMA.patch -ANDROID-Fixed-x86-regression.patch -ANDROID-x86-gki_defconfig-enable-DMA_CMA.patch -ANDROID-Removed-extraneous-configs-from-gki.patch -ANDROID-gki_defconfig-more-configs-for-partners.patch -ANDROID-gki_defconfig-workaround-to-enable-configs.patch -ANDROID-gki-cuttlefish-defconfigs-use-prebuilt-build-tools.patch -ANDROID-adding-usb-HCD-dummy-config-to-permit-usb-write-ops-on-init.patch -ANDROID-gki_defconfig-enable-more-configs.patch -ANDROID-gki_defconfig-disable-BRIDGE_NETFILTER.patch -ANDROID-sdcardfs-Enable-modular-sdcardfs.patch -ANDROID-vfs-Add-setattr2-for-filesystems-with-per-mount-permissions.patch -ANDROID-vfs-Add-permission2-for-filesystems-with-per-mount-permissions.patch -ANDROID-Add-show_options2-to-view-private-mount-data.patch -ANDROID-vfs-add-d_canonical_path-for-stacked-filesystem-support.patch -ANDROID-fs-Restore-vfs_path_lookup-export.patch -ANDROID-mnt-Add-filesystem-private-data-to-mount-points.patch -ANDROID-sdcardfs-Define-magic-value.patch -ANDROID-sdcardfs-Add-sdcardfs-filesystem.patch -ANDROID-cuttlefish-gki-_defconfig-Enable-CONFIG_SDCARD_FS.patch -ANDROID-mnt-Fix-null-pointer-dereference.patch -ANDROID-build-configs-switch-prebuilt-path-location.patch -ANDROID-Revert-x86-mm-Identify-the-end-of-the-kernel-area-to-be-reserved.patch -ANDROID-xfrm-remove-in_compat_syscall-checks.patch -ANDROID-Add-initial-rockpi4_defconfig.patch -ANDROID-label-cuttlefish-modules-for-gki.patch -ANDROID-staging-android-ion-Decouple-ION-page-pooling-from-ION-core.patch -ANDROID-staging-android-ion-Expose-ion_alloc-to-kernel-space.patch -ANDROID-dma-buf-Add-support-for-partial-cache-maintenance.patch -ANDROID-dma-buf-Add-support-for-mapping-buffers-with-DMA-attributes.patch -ANDROID-dma-buf-Add-support-to-get-flags-associated-with-a-buffer.patch -ANDROID-Removed-hardcoded-kernel-command-line-arguments.patch -ANDROID-gki_defconfig-disable-IP_PNP-ECRYPT_FS.patch -ANDROID-Removed-unnecessary-modules-from-cuttlefish.patch -ANDROID-Adding-GKI-Ramdisk-to-gki-config.patch -ANDROID-staging-ion-refactor-ion-s-buffer-manipulators-into-a-separate-file.patch -ANDROID-staging-ion-refactor-ion-s-dmabuf-manipulators-into-a-separate-file.patch -ANDROID-staging-ion-refactor-ion-s-heap-manipulators-into-a-separate-file.patch -ANDROID-staging-ion-Move-ion-heaps-into-their-own-directory.patch -ANDROID-staging-ion-refactor-ion-s-heap-API-into-linux-ion.h.patch -ANDROID-staging-ion-split-system-and-system-contig-heaps.patch -ANDROID-staging-ion-make-system-and-contig-heaps-modular.patch -ANDROID-staging-ion-Build-fix-for-mips.patch -ANDROID-fix-kernelci-build-break.patch -ANDROID-gki_defconfig-enable-CONFIG_TIPC.patch -ANDROID-gki_defconfig-set-CONFIG_NR_CPUS-32.patch -ANDROID-Revert-um-irq-don-t-set-the-chip-for-all-irqs.patch -ANDROID-Revert-um-remove-uses-of-variable-length-arrays.patch -ANDROID-sdcardfs-fix-fall-through-in-param-parsing.patch -ANDROID-gki_defconfig-Minimally-enable-EFI.patch -ANDROID-gki_defconfig-enable-CONFIG_SPARSEMEM_VMEMMAP.patch -ANDROID-gki_defconfig-enable-CONFIG_QCOM_-COMMAND_DB-RPMH-PDC.patch -ANDROID-refactor-build.config-files-to-remove-duplication.patch -ANDROID-staging-ion-move-uapi-ion.h-to-uapi-linux-ion.h.patch -ANDROID-staging-ion-reserve-specific-heap-ids-for-known-heap-types.patch -ANDROID-staging-ion-add-support-for-consistent-heap-ids.patch -ANDROID-staging-ion-Fix-uninitialized-variable-warning.patch -ANDROID-staging-ion-Add-support-for-heap-specific-dma_buf_ops.patch -ANDROID-staging-ion-Remove-unnecessary-ion-heap-ops.patch -ANDROID-create-build.configs-for-allmodconfig.patch -ANDROID-GKI-enable-CONFIG_SPI-for-x86.patch -ANDROID-GKI-enable-CONFIG_TIPC-for-x86.patch -ANDROID-Catch-rockpi4_defconfig-up-with-gki_defconfig.patch -ANDROID-first-pass-cuttlefish-GKI-modularization.patch -ANDROID-staging-ion-fix-off-by-1-error-in-heap-search.patch -ANDROID-staging-ion-uapi-match-the-existing-heap-type-enums.patch -ANDROID-staging-ion-export-ion_free-for-ion_heaps.patch -ANDROID-cuttlefish-overlayfs-regression.patch -ANDROID-Adding-SERIAL_OF_PLATFORM-module-to-gki.patch -ANDROID-Removed-extraneous-serial-8250-configs.patch -ANDROID-Log-which-device-failed-to-suspend-in-dpm_suspend_start.patch -ANDROID-CONFIG_MMC-m.patch -ANDROID-gki_defconfig-enable-CONFIG_UIO.patch -ANDROID-init-GKI-add-GKI_HACKS_TO_FIX.patch -ANDROID-init-GKI-enable-hidden-configs-for-DRM.patch -ANDROID-init-GKI-enable-hidden-configs-for-regmap.patch -ANDROID-init-GKI-enable-hidden-configs-for-SND_SOC.patch -ANDROID-init-GKI-enable-hidden-configs-for-GPIO.patch -ANDROID-gki_defconfig-Add-GKI_HACKS_to_FIX-config.patch -ANDROID-gki_defconfig-Enable-SERIAL_DEV_BUS.patch -ANDROID-gki_defconfig-Enable-HiSilicon-SoCs.patch -ANDROID-net-enable-wireless-core-features-with-GKI_LEGACY_WEXT_ALLCONFIG.patch -ANDROID-Remove-CONFIG_USELIB-from-x86-gki-config.patch -ANDROID-update-gki_defconfig.patch -ANDROID-update-arm64-gki_defconfig.patch -ANDROID-GKI-export-cma-symbols-for-cma-heap-as-a-module.patch -ANDROID-staging-ion-make-cma-heap-a-module.patch -ANDROID-usb-gadget-Fix-dependency-for-f_accessory.patch -ANDROID-allmodconfig-Force-gki_defconfig-as-base.patch -ANDROID-Fix-arm64-allmodconfig-build.patch -ANDROID-update-gki_defconfig-2.patch -ANDROID-sched-fair-EAS-Add-uclamp-support-to-find_energy_efficient_cpu.patch -ANDROID-sched-Unconditionally-honor-sync-flag-for-energy-aware-wakeups.patch -ANDROID-sched-fair-add-arch-scaling-function-for-max-frequency-capping.patch -ANDROID-cpufreq-arch_topology-implement-max-frequency-capping.patch -ANDROID-arm64-enable-max-frequency-capping.patch -ANDROID-arm-enable-max-frequency-capping.patch -ANDROID-sched-Update-max-cpu-capacity-in-case-of-max-frequency-constraints.patch -ANDROID-sched-Prevent-unnecessary-active-balance-of-single-task-in-sched-group.patch -ANDROID-sched-fair-Attempt-to-improve-throughput-for-asym-cap-systems.patch -ANDROID-sched-fair-Don-t-balance-misfits-if-it-would-overload-local-group.patch -ANDROID-sched-fair-Also-do-misfit-in-overloaded-groups.patch -ANDROID-arm64-defconfig-Enable-EAS-by-default.patch -ANDROID-sched-core-Add-a-latency-sensitive-flag-to-uclamp.patch -ANDROID-sched-Introduce-uclamp-latency-and-boost-wrapper.patch -ANDROID-sched-fair-Bias-EAS-placement-for-latency.patch -ANDROID-Initial-abi_gki_aarch64-definition.patch -ANDROID-Add-an-IOCTL-to-check-ION-ABI-version.patch -FROMGIT-driver-core-Add-fwnode_to_dev-to-look-up-device-from-fwnode.patch -FROMGIT-driver-core-Add-support-for-linking-devices-during-device-addition.patch -FROMGIT-of-property-Add-functional-dependency-link-from-DT-bindings.patch -FROMGIT-driver-core-Add-sync_state-driver-bus-callback.patch -FROMGIT-of-platform-Pause-resume-sync-state-during-init-and-of_platform_populate.patch -FROMGIT-of-property-Create-device-links-for-all-child-supplier-depencencies.patch -ANDROID-gki_defconfig-Enable-BPF_JIT-and-BPF_JIT_ALWAYS_ON.patch -ANDROID-gki_defconfig-enable-REGULATOR.patch -ANDROID-gki_defconfig-enable-CONFIG_NLS_.patch -ANDROID-Revert-kheaders-make-headers-archive-reproducible.patch -ANDROID-staging-ion-fix-sparse-warning-in-ion-system-heap.patch -ANDROID-gki_defconfig-enable-CONFIG_PARAVIRT-and-CONFIG_HYPERVISOR_GUEST.patch -ANDROID-gki_defconfig-enable-accelerated-AES-and-SHA-256.patch -ANDROID-gki_defconfig-enabled-CONFIG_TMPFS-explicitly.patch -ANDROID-gki_defconfig-Enable-CONFIG_DM_SNAPSHOT.patch -ANDROID-Fix-x86_64-allmodconfig-build.patch -ANDROID-clk-add-pre-and-post-change-rate-callbacks.patch -ANDROID-gki_defconfig-enable-fs-verity.patch -UPSTREAM-base-soc-Handle-custom-soc-information-sysfs-entries.patch -ANDROID-unconditionally-compile-sig_ok-in-struct-module.patch -ANDROID-gki_defconfig-remove-PWRSEQ_EMMC-and-PWRSEQ_SIMPLE.patch -ANDROID-sched-Honor-sync-flag-for-energy-aware-wakeups.patch diff --git a/samples/bpf/asm_goto_workaround.h b/samples/bpf/asm_goto_workaround.h index 7409722727ca16fcffa9c7bc5fe03f6a749cc4bf..7048bb3594d65be6d132d4103ee801fadf087b7e 100644 --- a/samples/bpf/asm_goto_workaround.h +++ b/samples/bpf/asm_goto_workaround.h @@ -3,7 +3,8 @@ #ifndef __ASM_GOTO_WORKAROUND_H #define __ASM_GOTO_WORKAROUND_H -/* this will bring in asm_volatile_goto macro definition +/* + * This will bring in asm_volatile_goto and asm_inline macro definitions * if enabled by compiler and config options. */ #include @@ -13,5 +14,15 @@ #define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto") #endif +/* + * asm_inline is defined as asm __inline in "include/linux/compiler_types.h" + * if supported by the kernel's CC (i.e CONFIG_CC_HAS_ASM_INLINE) which is not + * supported by CLANG. + */ +#ifdef asm_inline +#undef asm_inline +#define asm_inline asm +#endif + #define volatile(x...) volatile("") #endif diff --git a/samples/bpf/task_fd_query_user.c b/samples/bpf/task_fd_query_user.c index e3993805822355a544aa5af4b7f44804e27a965b..4c31b305e6efc08448fd7c4a63ce1a36e7fbee1d 100644 --- a/samples/bpf/task_fd_query_user.c +++ b/samples/bpf/task_fd_query_user.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "libbpf.h" #include "bpf_load.h" diff --git a/scripts/coccinelle/api/devm_platform_ioremap_resource.cocci b/scripts/coccinelle/api/devm_platform_ioremap_resource.cocci deleted file mode 100644 index 56a2e261d61d6209ab9957aa899d17ca469b142a..0000000000000000000000000000000000000000 --- a/scripts/coccinelle/api/devm_platform_ioremap_resource.cocci +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/// Use devm_platform_ioremap_resource helper which wraps -/// platform_get_resource() and devm_ioremap_resource() together. -/// -// Confidence: High -// Copyright: (C) 2019 Himanshu Jha GPLv2. -// Copyright: (C) 2019 Julia Lawall, Inria/LIP6. GPLv2. -// Keywords: platform_get_resource, devm_ioremap_resource, -// Keywords: devm_platform_ioremap_resource - -virtual patch -virtual report - -@r depends on patch && !report@ -expression e1, e2, arg1, arg2, arg3; -identifier id; -@@ - -( -- id = platform_get_resource(arg1, IORESOURCE_MEM, arg2); -| -- struct resource *id = platform_get_resource(arg1, IORESOURCE_MEM, arg2); -) - ... when != id -- e1 = devm_ioremap_resource(arg3, id); -+ e1 = devm_platform_ioremap_resource(arg1, arg2); - ... when != id -? id = e2 - -@r1 depends on patch && !report@ -identifier r.id; -type T; -@@ - -- T *id; - ...when != id - -@r2 depends on report && !patch@ -identifier id; -expression e1, e2, arg1, arg2, arg3; -position j0; -@@ - -( - id = platform_get_resource(arg1, IORESOURCE_MEM, arg2); -| - struct resource *id = platform_get_resource(arg1, IORESOURCE_MEM, arg2); -) - ... when != id - e1@j0 = devm_ioremap_resource(arg3, id); - ... when != id -? id = e2 - -@script:python depends on report && !patch@ -e1 << r2.e1; -j0 << r2.j0; -@@ - -msg = "WARNING: Use devm_platform_ioremap_resource for %s" % (e1) -coccilib.report.print_report(j0[0], msg) diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py index 6d2e09a2ad2f9204dbdb7c5c84522c45530e1342..2fa7bb83885f068e05648448267b3f590bfb2ab9 100644 --- a/scripts/gdb/linux/dmesg.py +++ b/scripts/gdb/linux/dmesg.py @@ -16,6 +16,8 @@ import sys from linux import utils +printk_log_type = utils.CachedType("struct printk_log") + class LxDmesg(gdb.Command): """Print Linux kernel log buffer.""" @@ -42,9 +44,14 @@ class LxDmesg(gdb.Command): b = utils.read_memoryview(inf, log_buf_addr, log_next_idx) log_buf = a.tobytes() + b.tobytes() + length_offset = printk_log_type.get_type()['len'].bitpos // 8 + text_len_offset = printk_log_type.get_type()['text_len'].bitpos // 8 + time_stamp_offset = printk_log_type.get_type()['ts_nsec'].bitpos // 8 + text_offset = printk_log_type.get_type().sizeof + pos = 0 while pos < log_buf.__len__(): - length = utils.read_u16(log_buf[pos + 8:pos + 10]) + length = utils.read_u16(log_buf, pos + length_offset) if length == 0: if log_buf_2nd_half == -1: gdb.write("Corrupted log buffer!\n") @@ -52,10 +59,11 @@ class LxDmesg(gdb.Command): pos = log_buf_2nd_half continue - text_len = utils.read_u16(log_buf[pos + 10:pos + 12]) - text = log_buf[pos + 16:pos + 16 + text_len].decode( + text_len = utils.read_u16(log_buf, pos + text_len_offset) + text_start = pos + text_offset + text = log_buf[text_start:text_start + text_len].decode( encoding='utf8', errors='replace') - time_stamp = utils.read_u64(log_buf[pos:pos + 8]) + time_stamp = utils.read_u64(log_buf, pos + time_stamp_offset) for line in text.splitlines(): msg = u"[{time:12.6f}] {line}\n".format( diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index 34e40e96dee2d7f7c29014d9edbf949b5ba1d0e5..7b7c2fafbc687d2f9cb0316089c8e124bf9a9fd0 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -15,7 +15,7 @@ import gdb import os import re -from linux import modules +from linux import modules, utils if hasattr(gdb, 'Breakpoint'): @@ -116,6 +116,12 @@ lx-symbols command.""" module_file = self._get_module_file(module_name) if module_file: + if utils.is_target_arch('s390'): + # Module text is preceded by PLT stubs on s390. + module_arch = module['arch'] + plt_offset = int(module_arch['plt_offset']) + plt_size = int(module_arch['plt_size']) + module_addr = hex(int(module_addr, 0) + plt_offset + plt_size) gdb.write("loading @{addr}: {filename}\n".format( addr=module_addr, filename=module_file)) cmdline = "add-symbol-file {filename} {addr}{sections}".format( diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index bc67126118c4d50ff1b6d567525eb9b40090e54d..ea94221dbd392733b873129b7c9060ef9da5b9a4 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -92,15 +92,16 @@ def read_memoryview(inf, start, length): return memoryview(inf.read_memory(start, length)) -def read_u16(buffer): +def read_u16(buffer, offset): + buffer_val = buffer[offset:offset + 2] value = [0, 0] - if type(buffer[0]) is str: - value[0] = ord(buffer[0]) - value[1] = ord(buffer[1]) + if type(buffer_val[0]) is str: + value[0] = ord(buffer_val[0]) + value[1] = ord(buffer_val[1]) else: - value[0] = buffer[0] - value[1] = buffer[1] + value[0] = buffer_val[0] + value[1] = buffer_val[1] if get_target_endianness() == LITTLE_ENDIAN: return value[0] + (value[1] << 8) @@ -108,18 +109,18 @@ def read_u16(buffer): return value[1] + (value[0] << 8) -def read_u32(buffer): +def read_u32(buffer, offset): if get_target_endianness() == LITTLE_ENDIAN: - return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16) + return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16) else: - return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16) + return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16) -def read_u64(buffer): +def read_u64(buffer, offset): if get_target_endianness() == LITTLE_ENDIAN: - return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32) + return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32) else: - return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32) + return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32) target_arch = None diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8d5169b911dfa70a4fd47296c8c8024787c52d2e..a244ae109562a709a32b23d64fc50a7c36f2cffd 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -534,6 +534,10 @@ static int parse_elf(struct elf_info *info, const char *filename) info->export_unused_gpl_sec = i; else if (strcmp(secname, "__ksymtab_gpl_future") == 0) info->export_gpl_future_sec = i; + else if (strcmp(secname, "__ksymtab_strings") == 0) + info->ksymtab_strings = (void *)hdr + + sechdrs[i].sh_offset - + sechdrs[i].sh_addr; if (sechdrs[i].sh_type == SHT_SYMTAB) { unsigned int sh_link_idx; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 8453d6ac2f77ebf46ebcc55eeaa045a1d9d052f1..deaccd0d0ec908b94475f9715e139385a310905a 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -134,6 +134,7 @@ struct elf_info { Elf_Section export_gpl_sec; Elf_Section export_unused_gpl_sec; Elf_Section export_gpl_future_sec; + char *ksymtab_strings; char *strtab; char *modinfo; unsigned int modinfo_len; diff --git a/scripts/nsdeps b/scripts/nsdeps index 3754dac13b312f16a655e73af68d4912c8da7c9b..dda6fbac016e413983e18982c1ca4b32e79f3c47 100644 --- a/scripts/nsdeps +++ b/scripts/nsdeps @@ -33,7 +33,7 @@ generate_deps() { if [ ! -f "$ns_deps_file" ]; then return; fi local mod_source_files=`cat $mod_file | sed -n 1p \ | sed -e 's/\.o/\.c/g' \ - | sed "s/[^ ]* */${srctree}\/&/g"` + | sed "s|[^ ]* *|${srctree}/&|g"` for ns in `cat $ns_deps_file`; do echo "Adding namespace $ns to module $mod_name (if needed)." generate_deps_for_ns $ns $mod_source_files diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 220dae0db3f17b945e674df6ddccd67a1a894f59..a2998b118ef9ed68ae1ffe8be1d4609beef806d5 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -93,7 +93,7 @@ scm_version() # Check for mercurial and a mercurial repo. if test -d .hg && hgid=`hg id 2>/dev/null`; then # Do we have an tagged version? If so, latesttagdistance == 1 - if [ "`hg log -r . --template '{latesttagdistance}'`" == "1" ]; then + if [ "`hg log -r . --template '{latesttagdistance}'`" = "1" ]; then id=`hg log -r . --template '{latesttag}'` printf '%s%s' -hg "$id" else diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c index 8a10b43daf74e5c3b86a06e19b4856b684dacc66..40b790536defaf8dcdad0655d4423f33c94dcd06 100644 --- a/security/lockdown/lockdown.c +++ b/security/lockdown/lockdown.c @@ -20,6 +20,7 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = { [LOCKDOWN_NONE] = "none", [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading", [LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port", + [LOCKDOWN_EFI_TEST] = "/dev/efi_test access", [LOCKDOWN_KEXEC] = "kexec of unsigned images", [LOCKDOWN_HIBERNATION] = "hibernation", [LOCKDOWN_PCI_ACCESS] = "direct PCI access", diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index de1f49352ccd072826b637930f22068caa94acdd..6371120fb0bf10a356d3279be570070b42995051 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -533,7 +533,7 @@ static int snd_compress_check_input(struct snd_compr_params *params) { /* first let's check the buffer parameter's */ if (params->buffer.fragment_size == 0 || - params->buffer.fragments > INT_MAX / params->buffer.fragment_size || + params->buffer.fragments > U32_MAX / params->buffer.fragment_size || params->buffer.fragments == 0) return -EINVAL; diff --git a/sound/core/jack.c b/sound/core/jack.c index fb26196571a7cbbe8ac11315c67e64b181979e44..e1594d0ca61fe3042d497414d471092478f62482 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -19,13 +19,16 @@ struct snd_jack_kctl { }; #ifdef CONFIG_SND_JACK_INPUT_DEV -static int jack_switch_types[SND_JACK_SWITCH_TYPES] = { +static int jack_switch_types[] = { SW_HEADPHONE_INSERT, SW_MICROPHONE_INSERT, SW_LINEOUT_INSERT, SW_JACK_PHYSICAL_INSERT, SW_VIDEOOUT_INSERT, SW_LINEIN_INSERT, + SW_HPHL_OVERCURRENT, + SW_HPHR_OVERCURRENT, + SW_UNSUPPORT_INSERT, }; #endif /* CONFIG_SND_JACK_INPUT_DEV */ @@ -236,7 +239,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, jack->type = type; - for (i = 0; i < SND_JACK_SWITCH_TYPES; i++) + for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) if (type & (1 << i)) input_set_capability(jack->input_dev, EV_SW, jack_switch_types[i]); diff --git a/sound/core/timer.c b/sound/core/timer.c index 5c9fbf3f43407a33aeb9dcbb338d6b98c9f18dc3..6b724d2ee2de9b0de0106bf5d2586e8f77677cd7 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -226,7 +226,8 @@ static int snd_timer_check_master(struct snd_timer_instance *master) return 0; } -static int snd_timer_close_locked(struct snd_timer_instance *timeri); +static int snd_timer_close_locked(struct snd_timer_instance *timeri, + struct device **card_devp_to_put); /* * open a timer instance @@ -238,6 +239,7 @@ int snd_timer_open(struct snd_timer_instance **ti, { struct snd_timer *timer; struct snd_timer_instance *timeri = NULL; + struct device *card_dev_to_put = NULL; int err; mutex_lock(®ister_mutex); @@ -261,7 +263,7 @@ int snd_timer_open(struct snd_timer_instance **ti, list_add_tail(&timeri->open_list, &snd_timer_slave_list); err = snd_timer_check_slave(timeri); if (err < 0) { - snd_timer_close_locked(timeri); + snd_timer_close_locked(timeri, &card_dev_to_put); timeri = NULL; } goto unlock; @@ -313,7 +315,7 @@ int snd_timer_open(struct snd_timer_instance **ti, timeri = NULL; if (timer->card) - put_device(&timer->card->card_dev); + card_dev_to_put = &timer->card->card_dev; module_put(timer->module); goto unlock; } @@ -323,12 +325,15 @@ int snd_timer_open(struct snd_timer_instance **ti, timer->num_instances++; err = snd_timer_check_master(timeri); if (err < 0) { - snd_timer_close_locked(timeri); + snd_timer_close_locked(timeri, &card_dev_to_put); timeri = NULL; } unlock: mutex_unlock(®ister_mutex); + /* put_device() is called after unlock for avoiding deadlock */ + if (card_dev_to_put) + put_device(card_dev_to_put); *ti = timeri; return err; } @@ -338,7 +343,8 @@ EXPORT_SYMBOL(snd_timer_open); * close a timer instance * call this with register_mutex down. */ -static int snd_timer_close_locked(struct snd_timer_instance *timeri) +static int snd_timer_close_locked(struct snd_timer_instance *timeri, + struct device **card_devp_to_put) { struct snd_timer *timer = timeri->timer; struct snd_timer_instance *slave, *tmp; @@ -395,7 +401,7 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri) timer->hw.close(timer); /* release a card refcount for safe disconnection */ if (timer->card) - put_device(&timer->card->card_dev); + *card_devp_to_put = &timer->card->card_dev; module_put(timer->module); } @@ -407,14 +413,18 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri) */ int snd_timer_close(struct snd_timer_instance *timeri) { + struct device *card_dev_to_put = NULL; int err; if (snd_BUG_ON(!timeri)) return -ENXIO; mutex_lock(®ister_mutex); - err = snd_timer_close_locked(timeri); + err = snd_timer_close_locked(timeri, &card_dev_to_put); mutex_unlock(®ister_mutex); + /* put_device() is called after unlock for avoiding deadlock */ + if (card_dev_to_put) + put_device(card_dev_to_put); return err; } EXPORT_SYMBOL(snd_timer_close); diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 73fee991bd75a500d25f074d78d6c71843505881..6c1497d9f52bac0e62b0cfce5bb0e59c64c70d31 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -252,8 +252,7 @@ int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob, return err; } -static unsigned int -map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s) +static int map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s) { unsigned int sec, sections, ch, channels; unsigned int pcm, midi, location; diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 211ca85acd8c4dbbedb93d7fc1fea806b3e8ced6..cfab60d88c921c507b5a0121a8e8f44d177e4d06 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -270,6 +270,11 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, ret = snd_hdac_ext_bus_link_power_up(link); + /* + * clear the register to invalidate all the output streams + */ + snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, + ML_LOSIDV_STREAM_MASK, 0); /* * wait for 521usec for codec to report status * HDA spec section 4.3 - Codec Discovery diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index d3999e7b070542e8aeb3a435abf52f6f44b022a8..7e7be8e4dcf9c3d7dd170ad2cbea0b949ec7f9e1 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c @@ -447,8 +447,6 @@ static void azx_int_disable(struct hdac_bus *bus) list_for_each_entry(azx_dev, &bus->stream_list, list) snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0); - synchronize_irq(bus->irq); - /* disable SIE for all streams */ snd_hdac_chip_writeb(bus, INTCTL, 0); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 240f4ca76391fbefa80074a182dc9ab88f4394e9..cf53fbd872ee34526d277bd4f479c1a5024b32b6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1348,9 +1348,9 @@ static int azx_free(struct azx *chip) } if (bus->chip_init) { - azx_stop_chip(chip); azx_clear_irq_pending(chip); azx_stop_all_streams(chip); + azx_stop_chip(chip); } if (bus->irq >= 0) @@ -2399,6 +2399,12 @@ static const struct pci_device_id azx_ids[] = { /* Icelake */ { PCI_DEVICE(0x8086, 0x34c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Jasperlake */ + { PCI_DEVICE(0x8086, 0x38c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Tigerlake */ + { PCI_DEVICE(0x8086, 0xa0c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Elkhart Lake */ { PCI_DEVICE(0x8086, 0x4b55), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index bca5de78e9ad577a08d885e1c519383797f4a3c9..b72553710ffbd91eaeaf503fe601eff9d3789258 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -145,6 +145,7 @@ struct hdmi_spec { struct snd_array pins; /* struct hdmi_spec_per_pin */ struct hdmi_pcm pcm_rec[16]; struct mutex pcm_lock; + struct mutex bind_lock; /* for audio component binding */ /* pcm_bitmap means which pcms have been assigned to pins*/ unsigned long pcm_bitmap; int pcm_used; /* counter of pcm_rec[] */ @@ -2258,7 +2259,7 @@ static int generic_hdmi_init(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int pin_idx; - mutex_lock(&spec->pcm_lock); + mutex_lock(&spec->bind_lock); spec->use_jack_detect = !codec->jackpoll_interval; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); @@ -2275,7 +2276,7 @@ static int generic_hdmi_init(struct hda_codec *codec) snd_hda_jack_detect_enable_callback(codec, pin_nid, jack_callback); } - mutex_unlock(&spec->pcm_lock); + mutex_unlock(&spec->bind_lock); return 0; } @@ -2382,6 +2383,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec) spec->ops = generic_standard_hdmi_ops; spec->dev_num = 1; /* initialize to 1 */ mutex_init(&spec->pcm_lock); + mutex_init(&spec->bind_lock); snd_hdac_register_chmap_ops(&codec->core, &spec->chmap); spec->chmap.ops.get_chmap = hdmi_get_chmap; @@ -2451,7 +2453,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, int i; spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops); - mutex_lock(&spec->pcm_lock); + mutex_lock(&spec->bind_lock); spec->use_acomp_notifier = use_acomp; spec->codec->relaxed_resume = use_acomp; /* reprogram each jack detection logic depending on the notifier */ @@ -2461,7 +2463,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, get_pin(spec, i)->pin_nid, use_acomp); } - mutex_unlock(&spec->pcm_lock); + mutex_unlock(&spec->bind_lock); } /* enable / disable the notifier via master bind / unbind */ @@ -3474,6 +3476,8 @@ static int patch_nvhdmi(struct hda_codec *codec) nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + codec->link_down_at_suspend = 1; + generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin); return 0; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b000b36ac3c627307381d7f7443e29133c077a81..80f66ba85f87664945777ef3fc7cf1abef4d63a6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -393,6 +393,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0700: case 0x10ec0701: case 0x10ec0703: + case 0x10ec0711: alc_update_coef_idx(codec, 0x10, 1<<15, 0); break; case 0x10ec0662: @@ -408,6 +409,9 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0672: alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */ break; + case 0x10ec0623: + alc_update_coef_idx(codec, 0x19, 1<<13, 0); + break; case 0x10ec0668: alc_update_coef_idx(codec, 0x7, 3<<13, 0); break; @@ -2919,6 +2923,7 @@ enum { ALC269_TYPE_ALC225, ALC269_TYPE_ALC294, ALC269_TYPE_ALC300, + ALC269_TYPE_ALC623, ALC269_TYPE_ALC700, }; @@ -2954,6 +2959,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC225: case ALC269_TYPE_ALC294: case ALC269_TYPE_ALC300: + case ALC269_TYPE_ALC623: case ALC269_TYPE_ALC700: ssids = alc269_ssids; break; @@ -5358,6 +5364,17 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec, } } +static void alc256_fixup_dell_xps_13_headphone_noise2(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + if (action != HDA_FIXUP_ACT_PRE_PROBE) + return; + + snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 0, HDA_AMP_VOLMASK, 1); + snd_hda_override_wcaps(codec, 0x1a, get_wcaps(codec, 0x1a) & ~AC_WCAP_IN_AMP); +} + static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, const struct hda_fixup *fix, int action) @@ -5822,6 +5839,7 @@ enum { ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, ALC275_FIXUP_DELL_XPS, ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, + ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2, ALC293_FIXUP_LENOVO_SPK_NOISE, ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, ALC255_FIXUP_DELL_SPK_NOISE, @@ -5869,6 +5887,7 @@ enum { ALC225_FIXUP_WYSE_AUTO_MUTE, ALC225_FIXUP_WYSE_DISABLE_MIC_VREF, ALC286_FIXUP_ACER_AIO_HEADSET_MIC, + ALC256_FIXUP_ASUS_HEADSET_MIC, ALC256_FIXUP_ASUS_MIC_NO_PRESENCE, ALC299_FIXUP_PREDATOR_SPK, ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC, @@ -6558,6 +6577,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE }, + [ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc256_fixup_dell_xps_13_headphone_noise2, + .chained = true, + .chain_id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE + }, [ALC293_FIXUP_LENOVO_SPK_NOISE] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_disable_aamix, @@ -6912,6 +6937,15 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE }, + [ALC256_FIXUP_ASUS_HEADSET_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x03a11020 }, /* headset mic with jack detect */ + { } + }, + .chained = true, + .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE + }, [ALC256_FIXUP_ASUS_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -7001,17 +7035,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), - SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE), SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP), - SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME), SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME), SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3), SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), @@ -7108,6 +7142,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), @@ -7186,6 +7221,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), @@ -7987,9 +8024,13 @@ static int patch_alc269(struct hda_codec *codec) spec->codec_variant = ALC269_TYPE_ALC300; spec->gen.mixer_nid = 0; /* no loopback on ALC300 */ break; + case 0x10ec0623: + spec->codec_variant = ALC269_TYPE_ALC623; + break; case 0x10ec0700: case 0x10ec0701: case 0x10ec0703: + case 0x10ec0711: spec->codec_variant = ALC269_TYPE_ALC700; spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */ alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */ @@ -9187,6 +9228,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269), HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269), HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0623, "ALC623", patch_alc269), HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861), HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd), HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861), @@ -9204,6 +9246,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269), HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269), HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0711, "ALC711", patch_alc269), HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc662), HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880), HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882), diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index e609abcf3220e71f9c600cec0aebf71067fb2003..eb709d52825965f3c53aa7432e01191569ab3193 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -901,16 +901,20 @@ static void max98373_slot_config(struct i2c_client *i2c, max98373->i_slot = value & 0xF; else max98373->i_slot = 1; - - max98373->reset_gpio = of_get_named_gpio(dev->of_node, + if (dev->of_node) { + max98373->reset_gpio = of_get_named_gpio(dev->of_node, "maxim,reset-gpio", 0); - if (!gpio_is_valid(max98373->reset_gpio)) { - dev_err(dev, "Looking up %s property in node %s failed %d\n", - "maxim,reset-gpio", dev->of_node->full_name, - max98373->reset_gpio); + if (!gpio_is_valid(max98373->reset_gpio)) { + dev_err(dev, "Looking up %s property in node %s failed %d\n", + "maxim,reset-gpio", dev->of_node->full_name, + max98373->reset_gpio); + } else { + dev_dbg(dev, "maxim,reset-gpio=%d", + max98373->reset_gpio); + } } else { - dev_dbg(dev, "maxim,reset-gpio=%d", - max98373->reset_gpio); + /* this makes reset_gpio as invalid */ + max98373->reset_gpio = -1; } if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value)) diff --git a/sound/soc/codecs/msm8916-wcd-digital.c b/sound/soc/codecs/msm8916-wcd-digital.c index 9fa5d44fdc79f57a3b274393dea4cd7f08a4b2a5..58b2468fb2a7139b8d7dbb35085ecbe5acb8215f 100644 --- a/sound/soc/codecs/msm8916-wcd-digital.c +++ b/sound/soc/codecs/msm8916-wcd-digital.c @@ -243,6 +243,10 @@ static const char *const rx_mix1_text[] = { "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3" }; +static const char * const rx_mix2_text[] = { + "ZERO", "IIR1", "IIR2" +}; + static const char *const dec_mux_text[] = { "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2" }; @@ -270,6 +274,16 @@ static const struct soc_enum rx3_mix1_inp_enum[] = { SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B2_CTL, 0, 6, rx_mix1_text), }; +/* RX1 MIX2 */ +static const struct soc_enum rx_mix2_inp1_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B3_CTL, + 0, 3, rx_mix2_text); + +/* RX2 MIX2 */ +static const struct soc_enum rx2_mix2_inp1_chain_enum = + SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B3_CTL, + 0, 3, rx_mix2_text); + /* DEC */ static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE( LPASS_CDC_CONN_TX_B1_CTL, 0, 6, dec_mux_text); @@ -309,6 +323,10 @@ static const struct snd_kcontrol_new rx3_mix1_inp2_mux = SOC_DAPM_ENUM( "RX3 MIX1 INP2 Mux", rx3_mix1_inp_enum[1]); static const struct snd_kcontrol_new rx3_mix1_inp3_mux = SOC_DAPM_ENUM( "RX3 MIX1 INP3 Mux", rx3_mix1_inp_enum[2]); +static const struct snd_kcontrol_new rx1_mix2_inp1_mux = SOC_DAPM_ENUM( + "RX1 MIX2 INP1 Mux", rx_mix2_inp1_chain_enum); +static const struct snd_kcontrol_new rx2_mix2_inp1_mux = SOC_DAPM_ENUM( + "RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum); /* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */ static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0); @@ -740,6 +758,10 @@ static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = { &rx3_mix1_inp2_mux), SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0, &rx3_mix1_inp3_mux), + SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0, + &rx1_mix2_inp1_mux), + SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0, + &rx2_mix2_inp1_mux), SND_SOC_DAPM_MUX("CIC1 MUX", SND_SOC_NOPM, 0, 0, &cic1_mux), SND_SOC_DAPM_MUX("CIC2 MUX", SND_SOC_NOPM, 0, 0, &cic2_mux), diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 762595de956c15662c245acf825c2cafb212b528..c506c9305043e115711cbac86fb22e77734b0d54 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1770,6 +1770,9 @@ static int rt5651_detect_headset(struct snd_soc_component *component) static bool rt5651_support_button_press(struct rt5651_priv *rt5651) { + if (!rt5651->hp_jack) + return false; + /* Button press support only works with internal jack-detection */ return (rt5651->hp_jack->status & SND_JACK_MICROPHONE) && rt5651->gpiod_hp_det == NULL; diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 1ef470700ed5fea954321884d705fc50ba9ccc23..c50b75ce82e0b727cd91fb0d17caf93088890da1 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -995,6 +995,16 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + rt5682->hs_jack = hs_jack; + + if (!hs_jack) { + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK, RT5682_JD1_DIS); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_JDH | RT5682_POW_JDL, 0); + return 0; + } + switch (rt5682->pdata.jd_src) { case RT5682_JD1: snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2, @@ -1032,8 +1042,6 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, break; } - rt5682->hs_jack = hs_jack; - return 0; } diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index c3d06e8bc54f20293f6490a56669e920eeae3a29..d5fb7f5dd551cb834ad77ae9b99ca453d7264008 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -533,13 +533,10 @@ static SOC_ENUM_SINGLE_DECL(dac_osr, static SOC_ENUM_SINGLE_DECL(adc_osr, WM8994_OVERSAMPLING, 1, osr_text); -static const struct snd_kcontrol_new wm8994_snd_controls[] = { +static const struct snd_kcontrol_new wm8994_common_snd_controls[] = { SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1_ADC1_RIGHT_VOLUME, 1, 119, 0, digital_tlv), -SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME, - WM8994_AIF1_ADC2_RIGHT_VOLUME, - 1, 119, 0, digital_tlv), SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2_ADC_RIGHT_VOLUME, 1, 119, 0, digital_tlv), @@ -556,8 +553,6 @@ SOC_ENUM("AIF2DACR Source", aif2dacr_src), SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), -SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME, - WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv), @@ -565,17 +560,12 @@ SOC_SINGLE_TLV("AIF1 Boost Volume", WM8994_AIF1_CONTROL_2, 10, 3, 0, aif_tlv), SOC_SINGLE_TLV("AIF2 Boost Volume", WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv), SOC_SINGLE("AIF1DAC1 EQ Switch", WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0), -SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0), SOC_SINGLE("AIF2 EQ Switch", WM8994_AIF2_EQ_GAINS_1, 0, 1, 0), WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch", WM8994_AIF1_DRC1_1, 2), WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch", WM8994_AIF1_DRC1_1, 1), WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch", WM8994_AIF1_DRC1_1, 0), -WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2), -WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1), -WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0), - WM8994_DRC_SWITCH("AIF2DAC DRC Switch", WM8994_AIF2_DRC_1, 2), WM8994_DRC_SWITCH("AIF2ADCL DRC Switch", WM8994_AIF2_DRC_1, 1), WM8994_DRC_SWITCH("AIF2ADCR DRC Switch", WM8994_AIF2_DRC_1, 0), @@ -594,9 +584,6 @@ SOC_SINGLE("Sidetone HPF Switch", WM8994_SIDETONE, 6, 1, 0), SOC_ENUM("AIF1ADC1 HPF Mode", aif1adc1_hpf), SOC_DOUBLE("AIF1ADC1 HPF Switch", WM8994_AIF1_ADC1_FILTERS, 12, 11, 1, 0), -SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf), -SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0), - SOC_ENUM("AIF2ADC HPF Mode", aif2adc_hpf), SOC_DOUBLE("AIF2ADC HPF Switch", WM8994_AIF2_ADC_FILTERS, 12, 11, 1, 0), @@ -637,6 +624,24 @@ SOC_SINGLE("AIF2DAC 3D Stereo Switch", WM8994_AIF2_DAC_FILTERS_2, 8, 1, 0), }; +/* Controls not available on WM1811 */ +static const struct snd_kcontrol_new wm8994_snd_controls[] = { +SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME, + WM8994_AIF1_ADC2_RIGHT_VOLUME, + 1, 119, 0, digital_tlv), +SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME, + WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), + +SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0), + +WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2), +WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1), +WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0), + +SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf), +SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0), +}; + static const struct snd_kcontrol_new wm8994_eq_controls[] = { SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0, eq_tlv), @@ -4258,13 +4263,15 @@ static int wm8994_component_probe(struct snd_soc_component *component) wm8994_handle_pdata(wm8994); wm_hubs_add_analogue_controls(component); - snd_soc_add_component_controls(component, wm8994_snd_controls, - ARRAY_SIZE(wm8994_snd_controls)); + snd_soc_add_component_controls(component, wm8994_common_snd_controls, + ARRAY_SIZE(wm8994_common_snd_controls)); snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets, ARRAY_SIZE(wm8994_dapm_widgets)); switch (control->type) { case WM8994: + snd_soc_add_component_controls(component, wm8994_snd_controls, + ARRAY_SIZE(wm8994_snd_controls)); snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, ARRAY_SIZE(wm8994_specific_dapm_widgets)); if (control->revision < 4) { @@ -4284,8 +4291,10 @@ static int wm8994_component_probe(struct snd_soc_component *component) } break; case WM8958: + snd_soc_add_component_controls(component, wm8994_snd_controls, + ARRAY_SIZE(wm8994_snd_controls)); snd_soc_add_component_controls(component, wm8958_snd_controls, - ARRAY_SIZE(wm8958_snd_controls)); + ARRAY_SIZE(wm8958_snd_controls)); snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, ARRAY_SIZE(wm8958_dapm_widgets)); if (control->revision < 1) { diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ae28d9907c30f58f2bd5a1ee8588b8b03fb9c399..9b8bb7bbe945daa4ad22db1264b44b0ac7f3a0f9 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1259,8 +1259,7 @@ static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len) } if (in) { - if (in & WMFW_CTL_FLAG_READABLE) - out |= rd; + out |= rd; if (in & WMFW_CTL_FLAG_WRITEABLE) out |= wr; if (in & WMFW_CTL_FLAG_VOLATILE) @@ -3697,11 +3696,16 @@ static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp) u32 xmalg, addr, magic; int i, ret; + alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id); + if (!alg_region) { + adsp_err(dsp, "No algorithm region found\n"); + return -EINVAL; + } + buf = wm_adsp_buffer_alloc(dsp); if (!buf) return -ENOMEM; - alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id); xmalg = dsp->ops->sys_config_size / sizeof(__be32); addr = alg_region->base + xmalg + ALG_XM_FIELD(magic); diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index a437567b8cee233a0dbebd52dfe1c70fe952dcce..4f6e58c3954a220fd0050c5d8c29089c0ee16622 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -308,6 +308,9 @@ static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_SPK("Spk", NULL), +}; + +static const struct snd_soc_dapm_widget dmic_widgets[] = { SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; @@ -318,10 +321,6 @@ static const struct snd_soc_dapm_route sof_map[] = { /* other jacks */ { "IN1P", NULL, "Headset Mic" }, - - /* digital mics */ - {"DMic", NULL, "SoC DMIC"}, - }; static const struct snd_soc_dapm_route speaker_map[] = { @@ -329,6 +328,11 @@ static const struct snd_soc_dapm_route speaker_map[] = { { "Spk", NULL, "Speaker" }, }; +static const struct snd_soc_dapm_route dmic_map[] = { + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, +}; + static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -342,6 +346,28 @@ static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } +static int dmic_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, + ARRAY_SIZE(dmic_widgets)); + if (ret) { + dev_err(card->dev, "DMic widget addition failed: %d\n", ret); + /* Don't need to add routes if widget addition failed */ + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map, + ARRAY_SIZE(dmic_map)); + + if (ret) + dev_err(card->dev, "DMic map addition failed: %d\n", ret); + + return ret; +} + /* sof audio machine driver for rt5682 codec */ static struct snd_soc_card sof_audio_card_rt5682 = { .name = "sof_rt5682", @@ -445,6 +471,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].name = "dmic01"; links[id].cpus = &cpus[id]; links[id].cpus->dai_name = "DMIC01 Pin"; + links[id].init = dmic_init; if (dmic_be_num > 1) { /* set up 2 BE links at most */ links[id + 1].name = "dmic16k"; @@ -576,6 +603,15 @@ static int sof_audio_probe(struct platform_device *pdev) /* need to get main clock from pmc */ if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); + if (IS_ERR(ctx->mclk)) { + ret = PTR_ERR(ctx->mclk); + + dev_err(&pdev->dev, + "Failed to get MCLK from pmc_plt_clk_3: %d\n", + ret); + return ret; + } + ret = clk_prepare_enable(ctx->mclk); if (ret < 0) { dev_err(&pdev->dev, @@ -621,8 +657,24 @@ static int sof_audio_probe(struct platform_device *pdev) &sof_audio_card_rt5682); } +static int sof_rt5682_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_component *component = NULL; + + for_each_card_components(card, component) { + if (!strcmp(component->name, rt5682_component[0].name)) { + snd_soc_component_set_jack(component, NULL, NULL); + break; + } + } + + return 0; +} + static struct platform_driver sof_audio = { .probe = sof_audio_probe, + .remove = sof_rt5682_remove, .driver = { .name = "sof_rt5682", .pm = &snd_soc_pm_ops, diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index af2d5a6124c8e122a8055d482b376d8df8be76c3..61c984f10d8e61199b7c02e287532039c6f3d9ed 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -677,7 +677,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev) ret = rockchip_pcm_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "Could not register PCM\n"); - return ret; + goto err_suspend; } return 0; diff --git a/sound/soc/samsung/arndale_rt5631.c b/sound/soc/samsung/arndale_rt5631.c index c213913eb98488f709c097e6d91b9f298bba5399..fd8c6642fb0dfbceeeb8a9170461287643667289 100644 --- a/sound/soc/samsung/arndale_rt5631.c +++ b/sound/soc/samsung/arndale_rt5631.c @@ -5,6 +5,7 @@ // Author: Claude #include +#include #include #include @@ -74,6 +75,17 @@ static struct snd_soc_card arndale_rt5631 = { .num_links = ARRAY_SIZE(arndale_rt5631_dai), }; +static void arndale_put_of_nodes(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *dai_link; + int i; + + for_each_card_prelinks(card, i, dai_link) { + of_node_put(dai_link->cpus->of_node); + of_node_put(dai_link->codecs->of_node); + } +} + static int arndale_audio_probe(struct platform_device *pdev) { int n, ret; @@ -103,18 +115,31 @@ static int arndale_audio_probe(struct platform_device *pdev) if (!arndale_rt5631_dai[0].codecs->of_node) { dev_err(&pdev->dev, "Property 'samsung,audio-codec' missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto err_put_of_nodes; } } ret = devm_snd_soc_register_card(card->dev, card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + goto err_put_of_nodes; + } + return 0; - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); - +err_put_of_nodes: + arndale_put_of_nodes(card); return ret; } +static int arndale_audio_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + arndale_put_of_nodes(card); + return 0; +} + static const struct of_device_id samsung_arndale_rt5631_of_match[] __maybe_unused = { { .compatible = "samsung,arndale-rt5631", }, { .compatible = "samsung,arndale-alc5631", }, @@ -129,6 +154,7 @@ static struct platform_driver arndale_audio_driver = { .of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match), }, .probe = arndale_audio_probe, + .remove = arndale_audio_remove, }; module_platform_driver(arndale_audio_driver); diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index bda5b958d0dc5c17b1681212fe5cb96377fd2b31..e9596c2096cd585334e6c99710cc6e3194a4f792 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -761,6 +761,7 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } /* set format */ + rdai->bit_clk_inv = 0; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: rdai->sys_delay = 0; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 12129559401ab931c7ec72342878050432bb6ced..42f72c9b78ba0428bea80b0b6ba2cfe7ac9d0a31 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1070,7 +1070,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } - snd_soc_dai_trigger(cpu_dai, substream, cmd); + ret = snd_soc_dai_trigger(cpu_dai, substream, cmd); if (ret < 0) return ret; @@ -1097,7 +1097,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, return ret; } - snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd); + ret = snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd); if (ret < 0) return ret; @@ -1146,6 +1146,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, { struct snd_soc_dpcm *dpcm; unsigned long flags; + char *name; /* only add new dpcms */ for_each_dpcm_be(fe, stream, dpcm) { @@ -1171,9 +1172,15 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, stream ? "<-" : "->", be->dai_link->name); #ifdef CONFIG_DEBUG_FS - dpcm->debugfs_state = debugfs_create_dir(be->dai_link->name, - fe->debugfs_dpcm_root); - debugfs_create_u32("state", 0644, dpcm->debugfs_state, &dpcm->state); + name = kasprintf(GFP_KERNEL, "%s:%s", be->dai_link->name, + stream ? "capture" : "playback"); + if (name) { + dpcm->debugfs_state = debugfs_create_dir(name, + fe->debugfs_dpcm_root); + debugfs_create_u32("state", 0644, dpcm->debugfs_state, + &dpcm->state); + kfree(name); + } #endif return 1; } diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index aa9a1fca46fa7832271ff0d3919959f94dfaa0a4..0fd032914a318b39d46f89ac8af1435de11ebba1 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1582,7 +1582,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, /* map user to kernel widget ID */ template.id = get_widget_id(le32_to_cpu(w->id)); - if (template.id < 0) + if ((int)template.id < 0) return template.id; /* strings are allocated here, but used and freed by the widget */ diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index a4983f90ff5b31694197b2d72c6e1cdf309e8fb9..2b8711eda362b97362ef2501080c099b7616bc52 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -60,13 +60,16 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; + bool change = false; + u32 value; /* update each channel */ for (i = 0; i < channels; i++) { - cdata->chanv[i].value = - mixer_to_ipc(ucontrol->value.integer.value[i], + value = mixer_to_ipc(ucontrol->value.integer.value[i], scontrol->volume_table, sm->max + 1); + change = change || (value != cdata->chanv[i].value); cdata->chanv[i].channel = i; + cdata->chanv[i].value = value; } /* notify DSP of mixer updates */ @@ -76,8 +79,7 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol, SOF_CTRL_TYPE_VALUE_CHAN_GET, SOF_CTRL_CMD_VOLUME, true); - - return 0; + return change; } int snd_sof_switch_get(struct snd_kcontrol *kcontrol, @@ -105,11 +107,15 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; + bool change = false; + u32 value; /* update each channel */ for (i = 0; i < channels; i++) { - cdata->chanv[i].value = ucontrol->value.integer.value[i]; + value = ucontrol->value.integer.value[i]; + change = change || (value != cdata->chanv[i].value); cdata->chanv[i].channel = i; + cdata->chanv[i].value = value; } /* notify DSP of mixer updates */ @@ -120,7 +126,7 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, SOF_CTRL_CMD_SWITCH, true); - return 0; + return change; } int snd_sof_enum_get(struct snd_kcontrol *kcontrol, @@ -148,11 +154,15 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, struct snd_sof_dev *sdev = scontrol->sdev; struct sof_ipc_ctrl_data *cdata = scontrol->control_data; unsigned int i, channels = scontrol->num_channels; + bool change = false; + u32 value; /* update each channel */ for (i = 0; i < channels; i++) { - cdata->chanv[i].value = ucontrol->value.enumerated.item[i]; + value = ucontrol->value.enumerated.item[i]; + change = change || (value != cdata->chanv[i].value); cdata->chanv[i].channel = i; + cdata->chanv[i].value = value; } /* notify DSP of enum updates */ @@ -163,7 +173,7 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, SOF_CTRL_CMD_ENUM, true); - return 0; + return change; } int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 479ba249e219af3ac4acbcd4f52622e51539d601..d62f51d33be148531916c887e6aa046328f5c2dc 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -273,6 +273,16 @@ config SND_SOC_SOF_HDA_AUDIO_CODEC Say Y if you want to enable HDAudio codecs with SOF. If unsure select "N". +config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1 + bool "SOF enable DMI Link L1" + help + This option enables DMI L1 for both playback and capture + and disables known workarounds for specific HDaudio platforms. + Only use to look into power optimizations on platforms not + affected by DMI L1 issues. This option is not recommended. + Say Y if you want to enable DMI Link L1 + If unsure, select "N". + endif ## SND_SOC_SOF_HDA_COMMON config SND_SOC_SOF_HDA_LINK_BASELINE diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index e282179263e8346f18a24d36389c2a71c8db9f47..80e2826fb447b28524268ccbf598f5f73e75abd7 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -37,6 +37,7 @@ #define MBOX_SIZE 0x1000 #define MBOX_DUMP_SIZE 0x30 #define EXCEPT_OFFSET 0x800 +#define EXCEPT_MAX_HDR_SIZE 0x400 /* DSP peripherals */ #define DMAC0_OFFSET 0xFE000 @@ -228,6 +229,11 @@ static void bdw_get_registers(struct snd_sof_dev *sdev, /* note: variable AR register array is not read */ /* then get panic info */ + if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) { + dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n", + xoops->arch_hdr.totalsize); + return; + } offset += xoops->arch_hdr.totalsize; sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info)); @@ -451,6 +457,7 @@ static int bdw_probe(struct snd_sof_dev *sdev) /* TODO: add offsets */ sdev->mmio_bar = BDW_DSP_BAR; sdev->mailbox_bar = BDW_DSP_BAR; + sdev->dsp_oops_offset = MBOX_OFFSET; /* PCI base */ mmio = platform_get_resource(pdev, IORESOURCE_MEM, diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 5e7a6aaa627a82490448b9a0ce549eb47b08264e..a1e514f7173952fe899923bd9ffda4009753674f 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -28,6 +28,7 @@ #define MBOX_OFFSET 0x144000 #define MBOX_SIZE 0x1000 #define EXCEPT_OFFSET 0x800 +#define EXCEPT_MAX_HDR_SIZE 0x400 /* DSP peripherals */ #define DMAC0_OFFSET 0x098000 @@ -126,6 +127,11 @@ static void byt_get_registers(struct snd_sof_dev *sdev, /* note: variable AR register array is not read */ /* then get panic info */ + if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) { + dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n", + xoops->arch_hdr.totalsize); + return; + } offset += xoops->arch_hdr.totalsize; sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info)); diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index bc41028a7a01de3d101412ebec768aeb3aa21d6f..df1909e1d95060b0b4ddba11d0294b490dca4b03 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -139,20 +139,16 @@ void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) */ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) { -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - struct hdac_bus *bus = sof_to_bus(sdev); -#endif u32 val; /* enable/disable audio dsp clock gating */ val = enable ? PCI_CGCTL_ADSPDCGE : 0; snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val); -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - /* enable/disable L1 support */ - val = enable ? SOF_HDA_VS_EM2_L1SEN : 0; - snd_hdac_chip_updatel(bus, VS_EM2, SOF_HDA_VS_EM2_L1SEN, val); -#endif + /* enable/disable DMI Link L1 support */ + val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0; + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, val); /* enable/disable audio dsp power gating */ val = enable ? 0 : PCI_PGCTL_ADSPPGD; diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 6427f0b3a2f113b7a7a13e65ce66e3e9c7ac8fc0..65c2af3fcaab71ebc559d8e2a4a1b8e9b173b5d1 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -44,6 +44,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, return -ENODEV; } hstream = &dsp_stream->hstream; + hstream->substream = NULL; /* allocate DMA buffer */ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index ad8d41f22e92ddcf958cd6ac7f4d13f789d8a5f8..2c744718840254fc30eec8a12dc39ac45d014a14 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -185,6 +185,17 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) direction == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture"); + /* + * Disable DMI Link L1 entry when capture stream is opened. + * Workaround to address a known issue with host DMA that results + * in xruns during pause/release in capture scenarios. + */ + if (!IS_ENABLED(SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) + if (stream && direction == SNDRV_PCM_STREAM_CAPTURE) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, 0); + return stream; } @@ -193,23 +204,43 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) { struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_stream *s; + bool active_capture_stream = false; + bool found = false; spin_lock_irq(&bus->reg_lock); - /* find used stream */ + /* + * close stream matching the stream tag + * and check if there are any open capture streams. + */ list_for_each_entry(s, &bus->stream_list, list) { - if (s->direction == direction && - s->opened && s->stream_tag == stream_tag) { + if (!s->opened) + continue; + + if (s->direction == direction && s->stream_tag == stream_tag) { s->opened = false; - spin_unlock_irq(&bus->reg_lock); - return 0; + found = true; + } else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) { + active_capture_stream = true; } } spin_unlock_irq(&bus->reg_lock); - dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag); - return -ENODEV; + /* Enable DMI L1 entry if there are no capture streams open */ + if (!IS_ENABLED(SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) + if (!active_capture_stream) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, + HDA_VS_INTEL_EM2_L1SEN); + + if (!found) { + dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag); + return -ENODEV; + } + + return 0; } int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index c72e9a09eee16a03da41267f127fdf0dbfc1b95d..06e84679087bc6bcb81a9988195475e6f042a354 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -35,6 +35,8 @@ #define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) #define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8) +#define EXCEPT_MAX_HDR_SIZE 0x400 + /* * Debug */ @@ -131,6 +133,11 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev, /* note: variable AR register array is not read */ /* then get panic info */ + if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) { + dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n", + xoops->arch_hdr.totalsize); + return; + } offset += xoops->arch_hdr.totalsize; sof_block_read(sdev, sdev->mmio_bar, offset, panic_info, sizeof(*panic_info)); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 5591841a1b6faf9a72aec8a94b9082e1561f1e75..23e430d3e056881853cc193e549ede0334b624da 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -39,7 +39,6 @@ #define SOF_HDA_WAKESTS 0x0E #define SOF_HDA_WAKESTS_INT_MASK ((1 << 8) - 1) #define SOF_HDA_RIRBSTS 0x5d -#define SOF_HDA_VS_EM2_L1SEN BIT(13) /* SOF_HDA_GCTL register bist */ #define SOF_HDA_GCTL_RESET BIT(0) @@ -228,6 +227,10 @@ #define HDA_DSP_REG_HIPCIE (HDA_DSP_IPC_BASE + 0x0C) #define HDA_DSP_REG_HIPCCTL (HDA_DSP_IPC_BASE + 0x10) +/* Intel Vendor Specific Registers */ +#define HDA_VS_INTEL_EM2 0x1030 +#define HDA_VS_INTEL_EM2_L1SEN BIT(13) + /* HIPCI */ #define HDA_DSP_REG_HIPCI_BUSY BIT(31) #define HDA_DSP_REG_HIPCI_MSG_MASK 0x7FFFFFFF diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index d7f32745fefe42a793baf869c33318b57a9e44a0..9a9a381a908dee467665c979fecc7d31fb58e3bc 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -546,10 +546,10 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) msecs_to_jiffies(sdev->boot_timeout)); if (ret == 0) { dev_err(sdev->dev, "error: firmware boot failure\n"); - /* after this point FW_READY msg should be ignored */ - sdev->boot_complete = true; snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX | SOF_DBG_TEXT | SOF_DBG_PCI); + /* after this point FW_READY msg should be ignored */ + sdev->boot_complete = true; return -EIO; } diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index e3f6a6dc0f368af0614c1080cbfb678f9e832958..2b876d4974476bd359d4f530cabfeb92776b3164 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -244,7 +244,7 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; - int ret; + int ret, err = 0; /* nothing to do for BE */ if (rtd->dai_link->no_pcm) @@ -254,26 +254,26 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream) if (!spcm) return -EINVAL; - if (!spcm->prepared[substream->stream]) - return 0; - dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); + if (spcm->prepared[substream->stream]) { + ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); + if (ret < 0) + err = ret; + } snd_pcm_lib_free_pages(substream); cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); - if (ret < 0) - return ret; - ret = snd_sof_pcm_platform_hw_free(sdev, substream); - if (ret < 0) + if (ret < 0) { dev_err(sdev->dev, "error: platform hw free failed\n"); + err = ret; + } - return ret; + return err; } static int sof_pcm_prepare(struct snd_pcm_substream *substream) @@ -323,6 +323,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct sof_ipc_stream stream; struct sof_ipc_reply reply; bool reset_hw_params = false; + bool ipc_first = false; int ret; /* nothing to do for BE */ @@ -343,6 +344,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE; + ipc_first = true; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; @@ -363,6 +365,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; + ipc_first = true; reset_hw_params = true; break; default: @@ -370,12 +373,22 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return -EINVAL; } - snd_sof_pcm_platform_trigger(sdev, substream, cmd); + /* + * DMA and IPC sequence is different for start and stop. Need to send + * STOP IPC before stop DMA + */ + if (!ipc_first) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); /* send IPC to the DSP */ ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, sizeof(stream), &reply, sizeof(reply)); + /* need to STOP DMA even if STOP IPC failed */ + if (ipc_first) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); + + /* free PCM if reset_hw_params is set and the STOP IPC is successful */ if (!ret && reset_hw_params) ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index fc85efbad378c7308e4c410b5a9e6f6d3683c07b..0aabb3190ddc9735aebdbc494805a28f9b97d035 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -920,7 +920,9 @@ static void sof_parse_word_tokens(struct snd_soc_component *scomp, for (j = 0; j < count; j++) { /* match token type */ if (!(tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD || - tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT)) + tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT || + tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE || + tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL)) continue; /* match token id */ diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index d7501f88aaa630afb61fe87352eb1bcb287b9700..a4060813bc74c7b088bdebfa39dc1d624a2b3cc6 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -505,10 +505,20 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai, if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) { ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, - (unsigned int)~SAI_XCR1_NODIV); + freq ? 0 : SAI_XCR1_NODIV); if (ret < 0) return ret; + /* Assume shutdown if requested frequency is 0Hz */ + if (!freq) { + /* Release mclk rate only if rate was actually set */ + if (sai->mclk_rate) { + clk_rate_exclusive_put(sai->sai_mclk); + sai->mclk_rate = 0; + } + return 0; + } + /* If master clock is used, set parent clock now */ ret = stm32_sai_set_parent_clock(sai, freq); if (ret) @@ -1093,15 +1103,6 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0); - regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, - SAI_XCR1_NODIV); - - /* Release mclk rate only if rate was actually set */ - if (sai->mclk_rate) { - clk_rate_exclusive_put(sai->sai_mclk); - sai->mclk_rate = 0; - } - clk_disable_unprepare(sai->sai_ck); spin_lock_irqsave(&sai->irq_lock, flags); diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 33cd26763c0ee5d4509e156d43d83a6c50971988..ff5ab24f3bd1f36013ffd343b39139d48a5feff8 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -348,6 +348,9 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, ep = 0x84; ifnum = 0; goto add_sync_ep_from_ifnum; + case USB_ID(0x0582, 0x01d8): /* BOSS Katana */ + /* BOSS Katana amplifiers do not need quirks */ + return 0; } if (attr == USB_ENDPOINT_SYNC_ASYNC && diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index fbfde996fee76df28b56439c0030fb1cb0de7da3..0bbe1201a6ac8c57c7ae533e516c92fe67f832a7 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1657,6 +1657,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, case 0x23ba: /* Playback Designs */ case 0x25ce: /* Mytek devices */ case 0x278b: /* Rotel? */ + case 0x292b: /* Gustard/Ess based devices */ case 0x2ab6: /* T+A devices */ case 0x3842: /* EVGA */ case 0xc502: /* HiBy devices */ diff --git a/sound/usb/validate.c b/sound/usb/validate.c index 3c8f73a0eb12254385f9b2ed007bafc46ee74109..a5e584b60dcd83efd9b6732980e72e074e160c31 100644 --- a/sound/usb/validate.c +++ b/sound/usb/validate.c @@ -75,7 +75,7 @@ static bool validate_processing_unit(const void *p, if (d->bLength < sizeof(*d)) return false; - len = d->bLength < sizeof(*d) + d->bNrInPins; + len = sizeof(*d) + d->bNrInPins; if (d->bLength < len) return false; switch (v->protocol) { diff --git a/tools/arch/x86/include/uapi/asm/svm.h b/tools/arch/x86/include/uapi/asm/svm.h index a9731f8a480f3bca0785c94e870c74be6c191a67..2e8a30f06c74641cead87f4f460089f081c63ea7 100644 --- a/tools/arch/x86/include/uapi/asm/svm.h +++ b/tools/arch/x86/include/uapi/asm/svm.h @@ -75,6 +75,7 @@ #define SVM_EXIT_MWAIT 0x08b #define SVM_EXIT_MWAIT_COND 0x08c #define SVM_EXIT_XSETBV 0x08d +#define SVM_EXIT_RDPRU 0x08e #define SVM_EXIT_NPF 0x400 #define SVM_EXIT_AVIC_INCOMPLETE_IPI 0x401 #define SVM_EXIT_AVIC_UNACCELERATED_ACCESS 0x402 diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h index f01950aa7faedb951bfc8480536f9e4fe0a8b408..3eb8411ab60efb14e4890c711569bfe3259c8687 100644 --- a/tools/arch/x86/include/uapi/asm/vmx.h +++ b/tools/arch/x86/include/uapi/asm/vmx.h @@ -86,6 +86,8 @@ #define EXIT_REASON_PML_FULL 62 #define EXIT_REASON_XSAVES 63 #define EXIT_REASON_XRSTORS 64 +#define EXIT_REASON_UMWAIT 67 +#define EXIT_REASON_TPAUSE 68 #define VMX_EXIT_REASONS \ { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ @@ -144,7 +146,9 @@ { EXIT_REASON_RDSEED, "RDSEED" }, \ { EXIT_REASON_PML_FULL, "PML_FULL" }, \ { EXIT_REASON_XSAVES, "XSAVES" }, \ - { EXIT_REASON_XRSTORS, "XRSTORS" } + { EXIT_REASON_XRSTORS, "XRSTORS" }, \ + { EXIT_REASON_UMWAIT, "UMWAIT" }, \ + { EXIT_REASON_TPAUSE, "TPAUSE" } #define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2 diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile index fbf5e4a0cb9c9cdb7c3c13c28e2d4cf3b5b90f3b..5d1995fd369c696d919240f66b9dad92ff4612ab 100644 --- a/tools/bpf/Makefile +++ b/tools/bpf/Makefile @@ -12,7 +12,11 @@ INSTALL ?= install CFLAGS += -Wall -O2 CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/include/uapi -I$(srctree)/include -ifeq ($(srctree),) +# This will work when bpf is built in tools env. where srctree +# isn't set and when invoked from selftests build, where srctree +# is set to ".". building_out_of_srctree is undefined for in srctree +# builds +ifndef building_out_of_srctree srctree := $(patsubst %/,%,$(dir $(CURDIR))) srctree := $(patsubst %/,%,$(dir $(srctree))) endif diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index 233efbb1c81ca153c64693814d8518756284e1d0..52641d8ca9e83f25b983f3cc6be115c37bad2d98 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -999,6 +999,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_ARM_PTRAUTH_GENERIC 172 #define KVM_CAP_PMU_EVENT_FILTER 173 #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 +#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175 #ifdef KVM_CAP_IRQ_ROUTING @@ -1145,6 +1146,7 @@ struct kvm_dirty_tlb { #define KVM_REG_S390 0x5000000000000000ULL #define KVM_REG_ARM64 0x6000000000000000ULL #define KVM_REG_MIPS 0x7000000000000000ULL +#define KVM_REG_RISCV 0x8000000000000000ULL #define KVM_REG_SIZE_SHIFT 52 #define KVM_REG_SIZE_MASK 0x00f0000000000000ULL diff --git a/tools/include/uapi/linux/sched.h b/tools/include/uapi/linux/sched.h index b3105ac1381a8d8651f7f2fbe6b700bd745ead01..99335e1f4a275b1dbc86219a6dee7701b18fd624 100644 --- a/tools/include/uapi/linux/sched.h +++ b/tools/include/uapi/linux/sched.h @@ -33,8 +33,31 @@ #define CLONE_NEWNET 0x40000000 /* New network namespace */ #define CLONE_IO 0x80000000 /* Clone io context */ -/* - * Arguments for the clone3 syscall +#ifndef __ASSEMBLY__ +/** + * struct clone_args - arguments for the clone3 syscall + * @flags: Flags for the new process as listed above. + * All flags are valid except for CSIGNAL and + * CLONE_DETACHED. + * @pidfd: If CLONE_PIDFD is set, a pidfd will be + * returned in this argument. + * @child_tid: If CLONE_CHILD_SETTID is set, the TID of the + * child process will be returned in the child's + * memory. + * @parent_tid: If CLONE_PARENT_SETTID is set, the TID of + * the child process will be returned in the + * parent's memory. + * @exit_signal: The exit_signal the parent process will be + * sent when the child exits. + * @stack: Specify the location of the stack for the + * child process. + * @stack_size: The size of the stack for the child process. + * @tls: If CLONE_SETTLS is set, the tls descriptor + * is set to tls. + * + * The structure is versioned by size and thus extensible. + * New struct members must go at the end of the struct and + * must be properly 64bit aligned. */ struct clone_args { __aligned_u64 flags; @@ -46,6 +69,9 @@ struct clone_args { __aligned_u64 stack_size; __aligned_u64 tls; }; +#endif + +#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */ /* * Scheduling policies diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index c6f94cffe06e106549b835e9970b6aeeb577c9a8..56ce6292071b1d3575c26aafaea7967004d5a4cc 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -8,7 +8,11 @@ LIBBPF_MAJOR_VERSION := $(firstword $(subst ., ,$(LIBBPF_VERSION))) MAKEFLAGS += --no-print-directory -ifeq ($(srctree),) +# This will work when bpf is built in tools env. where srctree +# isn't set and when invoked from selftests build, where srctree +# is a ".". building_out_of_srctree is undefined for in srctree +# builds +ifndef building_out_of_srctree srctree := $(patsubst %/,%,$(dir $(CURDIR))) srctree := $(patsubst %/,%,$(dir $(srctree))) srctree := $(patsubst %/,%,$(dir $(srctree))) @@ -110,6 +114,9 @@ override CFLAGS += $(INCLUDES) override CFLAGS += -fvisibility=hidden override CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +# flags specific for shared library +SHLIB_FLAGS := -DSHARED + ifeq ($(VERBOSE),1) Q = else @@ -126,14 +133,17 @@ all: export srctree OUTPUT CC LD CFLAGS V include $(srctree)/tools/build/Makefile.include -BPF_IN := $(OUTPUT)libbpf-in.o +SHARED_OBJDIR := $(OUTPUT)sharedobjs/ +STATIC_OBJDIR := $(OUTPUT)staticobjs/ +BPF_IN_SHARED := $(SHARED_OBJDIR)libbpf-in.o +BPF_IN_STATIC := $(STATIC_OBJDIR)libbpf-in.o VERSION_SCRIPT := libbpf.map LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET)) LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE)) PC_FILE := $(addprefix $(OUTPUT),$(PC_FILE)) -GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN) | \ +GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN_SHARED) | \ cut -d "@" -f1 | sed 's/_v[0-9]_[0-9]_[0-9].*//' | \ awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$8}' | \ sort -u | wc -l) @@ -155,7 +165,7 @@ all: fixdep all_cmd: $(CMD_TARGETS) check -$(BPF_IN): force elfdep bpfdep +$(BPF_IN_SHARED): force elfdep bpfdep @(test -f ../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \ (diff -B ../../include/uapi/linux/bpf.h ../../../include/uapi/linux/bpf.h >/dev/null) || \ echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf.h' differs from latest version at 'include/uapi/linux/bpf.h'" >&2 )) || true @@ -171,17 +181,20 @@ $(BPF_IN): force elfdep bpfdep @(test -f ../../include/uapi/linux/if_xdp.h -a -f ../../../include/uapi/linux/if_xdp.h && ( \ (diff -B ../../include/uapi/linux/if_xdp.h ../../../include/uapi/linux/if_xdp.h >/dev/null) || \ echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/if_xdp.h' differs from latest version at 'include/uapi/linux/if_xdp.h'" >&2 )) || true - $(Q)$(MAKE) $(build)=libbpf + $(Q)$(MAKE) $(build)=libbpf OUTPUT=$(SHARED_OBJDIR) CFLAGS="$(CFLAGS) $(SHLIB_FLAGS)" + +$(BPF_IN_STATIC): force elfdep bpfdep + $(Q)$(MAKE) $(build)=libbpf OUTPUT=$(STATIC_OBJDIR) $(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION) -$(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN) +$(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN_SHARED) $(QUIET_LINK)$(CC) --shared -Wl,-soname,libbpf.so.$(LIBBPF_MAJOR_VERSION) \ -Wl,--version-script=$(VERSION_SCRIPT) $^ -lelf -o $@ @ln -sf $(@F) $(OUTPUT)libbpf.so @ln -sf $(@F) $(OUTPUT)libbpf.so.$(LIBBPF_MAJOR_VERSION) -$(OUTPUT)libbpf.a: $(BPF_IN) +$(OUTPUT)libbpf.a: $(BPF_IN_STATIC) $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ $(OUTPUT)test_libbpf: test_libbpf.cpp $(OUTPUT)libbpf.a @@ -197,7 +210,7 @@ check: check_abi check_abi: $(OUTPUT)libbpf.so @if [ "$(GLOBAL_SYM_COUNT)" != "$(VERSIONED_SYM_COUNT)" ]; then \ - echo "Warning: Num of global symbols in $(BPF_IN)" \ + echo "Warning: Num of global symbols in $(BPF_IN_SHARED)" \ "($(GLOBAL_SYM_COUNT)) does NOT match with num of" \ "versioned symbols in $^ ($(VERSIONED_SYM_COUNT))." \ "Please make sure all LIBBPF_API symbols are" \ @@ -255,9 +268,9 @@ config-clean: $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null clean: - $(call QUIET_CLEAN, libbpf) $(RM) $(TARGETS) $(CXX_TEST_TARGET) \ + $(call QUIET_CLEAN, libbpf) $(RM) -rf $(TARGETS) $(CXX_TEST_TARGET) \ *.o *~ *.a *.so *.so.$(LIBBPF_MAJOR_VERSION) .*.d .*.cmd \ - *.pc LIBBPF-CFLAGS + *.pc LIBBPF-CFLAGS $(SHARED_OBJDIR) $(STATIC_OBJDIR) $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 2e83a34f8c79a7e018a65ad6cdcd0ea3dc5b4764..98216a69c32f0d42ce4702c515c4881568243229 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -34,6 +34,22 @@ (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)) #endif +/* Symbol versioning is different between static and shared library. + * Properly versioned symbols are needed for shared library, but + * only the symbol of the new version is needed for static library. + */ +#ifdef SHARED +# define COMPAT_VERSION(internal_name, api_name, version) \ + asm(".symver " #internal_name "," #api_name "@" #version); +# define DEFAULT_VERSION(internal_name, api_name, version) \ + asm(".symver " #internal_name "," #api_name "@@" #version); +#else +# define COMPAT_VERSION(internal_name, api_name, version) +# define DEFAULT_VERSION(internal_name, api_name, version) \ + extern typeof(internal_name) api_name \ + __attribute__((alias(#internal_name))); +#endif + extern void libbpf_print(enum libbpf_print_level level, const char *format, ...) __attribute__((format(printf, 2, 3))); diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c index 24fa313524fb216fa9390725c99fc4d0766c1564..a902838f9fccd37b63554363b5308729f7871bd3 100644 --- a/tools/lib/bpf/xsk.c +++ b/tools/lib/bpf/xsk.c @@ -261,8 +261,8 @@ int xsk_umem__create_v0_0_2(struct xsk_umem **umem_ptr, void *umem_area, return xsk_umem__create_v0_0_4(umem_ptr, umem_area, size, fill, comp, &config); } -asm(".symver xsk_umem__create_v0_0_2, xsk_umem__create@LIBBPF_0.0.2"); -asm(".symver xsk_umem__create_v0_0_4, xsk_umem__create@@LIBBPF_0.0.4"); +COMPAT_VERSION(xsk_umem__create_v0_0_2, xsk_umem__create, LIBBPF_0.0.2) +DEFAULT_VERSION(xsk_umem__create_v0_0_4, xsk_umem__create, LIBBPF_0.0.4) static int xsk_load_xdp_prog(struct xsk_socket *xsk) { diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 3542b6ab9813b5bf7d79a95aafbb1400cef13c2a..e69f44941aad9a7bed7f4a3cbc0d218f84985081 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2635,6 +2635,7 @@ static int build_cl_output(char *cl_sort, bool no_source) bool add_sym = false; bool add_dso = false; bool add_src = false; + int ret = 0; if (!buf) return -ENOMEM; @@ -2653,7 +2654,8 @@ static int build_cl_output(char *cl_sort, bool no_source) add_dso = true; } else if (strcmp(tok, "offset")) { pr_err("unrecognized sort token: %s\n", tok); - return -EINVAL; + ret = -EINVAL; + goto err; } } @@ -2676,13 +2678,15 @@ static int build_cl_output(char *cl_sort, bool no_source) add_sym ? "symbol," : "", add_dso ? "dso," : "", add_src ? "cl_srcline," : "", - "node") < 0) - return -ENOMEM; + "node") < 0) { + ret = -ENOMEM; + goto err; + } c2c.show_src = add_src; - +err: free(buf); - return 0; + return ret; } static int setup_coalesce(const char *coalesce, bool no_source) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 1e61e353f579bc6e6910eb9906485f2115eac69d..9661671cc26ec29029b895aa3a4c630a31e65cd0 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -691,6 +691,7 @@ static char *compact_gfp_flags(char *gfp_flags) new = realloc(new_flags, len + strlen(cpt) + 2); if (new == NULL) { free(new_flags); + free(orig_flags); return NULL; } diff --git a/tools/perf/jvmti/Build b/tools/perf/jvmti/Build index 1e148bbdf820f69efcd97fa07ec4befb993b1751..202cadaaf097bdbb0135bca174f7fa92bf208aa9 100644 --- a/tools/perf/jvmti/Build +++ b/tools/perf/jvmti/Build @@ -2,7 +2,7 @@ jvmti-y += libjvmti.o jvmti-y += jvmti_agent.o # For strlcpy -jvmti-y += libstring.o +jvmti-y += libstring.o libctype.o CFLAGS_jvmti = -fPIC -DPIC -I$(JDIR)/include -I$(JDIR)/include/linux CFLAGS_REMOVE_jvmti = -Wmissing-declarations @@ -15,3 +15,7 @@ CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PE $(OUTPUT)jvmti/libstring.o: ../lib/string.c FORCE $(call rule_mkdir) $(call if_changed_dep,cc_o_c) + +$(OUTPUT)jvmti/libctype.o: ../lib/ctype.c FORCE + $(call rule_mkdir) + $(call if_changed_dep,cc_o_c) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 4036c7f7b0fbcfa1c8c61ab115d71324fd3334b7..e42bf572358c7edd584ad43309f0e02a336dfebd 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1758,7 +1758,7 @@ static int symbol__disassemble_bpf(struct symbol *sym, info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id); if (!info_node) { - return SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF; + ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF; goto out; } info_linear = info_node->info_linear; diff --git a/tools/perf/util/copyfile.c b/tools/perf/util/copyfile.c index 3fa0db1366676aa2ac047d6a5674e04c453837ba..47e03de7c2358a0d2c7150190a5b811b4ef7b133 100644 --- a/tools/perf/util/copyfile.c +++ b/tools/perf/util/copyfile.c @@ -101,14 +101,16 @@ static int copyfile_mode_ns(const char *from, const char *to, mode_t mode, if (tofd < 0) goto out; - if (fchmod(tofd, mode)) - goto out_close_to; - if (st.st_size == 0) { /* /proc? do it slowly... */ err = slow_copyfile(from, tmp, nsi); + if (!err && fchmod(tofd, mode)) + err = -1; goto out_close_to; } + if (fchmod(tofd, mode)) + goto out_close_to; + nsinfo__mountns_enter(nsi, &nsc); fromfd = open(from, O_RDONLY); nsinfo__mountns_exit(&nsc); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d277a98e62df8f769dbf88e45b6b635b085050e6..de79c735e4411b182ce9da0d4d8baee120eaed15 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1659,7 +1659,7 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list, is_open = false; if (c2->leader == leader) { if (is_open) - perf_evsel__close(&evsel->core); + perf_evsel__close(&c2->core); c2->leader = c2; c2->core.nr_members = 0; } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 86d9396cb131cdca6731da256f3a10460827b6cf..becc2d1094237580901dfe0578ad63900cc77635 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1296,8 +1296,10 @@ static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp) continue; if (WARN_ONCE(cnt >= size, - "failed to write MEM_TOPOLOGY, way too many nodes\n")) + "failed to write MEM_TOPOLOGY, way too many nodes\n")) { + closedir(dir); return -1; + } ret = memory_node__read(&nodes[cnt++], idx); } diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 5eda6e19c94745e4df80a0df5c25b91919f47d2e..ae56c766eda16e0d51560fcea4532843d2c96bb8 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -154,8 +154,10 @@ static int rm_rf_depth_pat(const char *path, int depth, const char **pat) if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; - if (!match_pat(d->d_name, pat)) - return -2; + if (!match_pat(d->d_name, pat)) { + ret = -2; + break; + } scnprintf(namebuf, sizeof(namebuf), "%s/%s", path, d->d_name); diff --git a/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c b/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c index 6cbeea7b4bf16ab1d7a49aa8379ef753e35ce304..8547ecbdc61ff3193465de061ebb5fb94109129a 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c +++ b/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c @@ -195,7 +195,7 @@ static void run_test(int cgroup_fd) if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread, (void *)&server_fd))) - goto close_bpf_object; + goto close_server_fd; pthread_mutex_lock(&server_started_mtx); pthread_cond_wait(&server_started, &server_started_mtx); diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c index a82da555b1b0217af5c1d84faaeb8b08835c006e..f4cd60d6fba2e1c8ef4142b493a663204670c620 100644 --- a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c +++ b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c @@ -260,13 +260,14 @@ void test_tcp_rtt(void) if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread, (void *)&server_fd))) - goto close_cgroup_fd; + goto close_server_fd; pthread_mutex_lock(&server_started_mtx); pthread_cond_wait(&server_started, &server_started_mtx); pthread_mutex_unlock(&server_started_mtx); CHECK_FAIL(run_test(cgroup_fd, server_fd)); +close_server_fd: close(server_fd); close_cgroup_fd: close(cgroup_fd); diff --git a/tools/testing/selftests/bpf/test_flow_dissector.sh b/tools/testing/selftests/bpf/test_flow_dissector.sh index d23d4da66b834858a2307517b65529aba0622e86..e2d06191bd35c67cbdbd036716c1475723953ae7 100755 --- a/tools/testing/selftests/bpf/test_flow_dissector.sh +++ b/tools/testing/selftests/bpf/test_flow_dissector.sh @@ -63,6 +63,9 @@ fi # Setup tc qdisc add dev lo ingress +echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter +echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter +echo 0 > /proc/sys/net/ipv4/conf/lo/rp_filter echo "Testing IPv4..." # Drops all IP/UDP packets coming from port 9 diff --git a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh index acf7a74f97cd9bb61420205d34cea328f2380084..59ea56945e6cd6819dc12fe337f324d784449e48 100755 --- a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh +++ b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh @@ -314,15 +314,15 @@ test_gso() command -v nc >/dev/null 2>&1 || \ { echo >&2 "nc is not available: skipping TSO tests"; return; } - # listen on IPv*_DST, capture TCP into $TMPFILE + # listen on port 9000, capture TCP into $TMPFILE if [ "${PROTO}" == "IPv4" ] ; then IP_DST=${IPv4_DST} ip netns exec ${NS3} bash -c \ - "nc -4 -l -s ${IPv4_DST} -p 9000 > ${TMPFILE} &" + "nc -4 -l -p 9000 > ${TMPFILE} &" elif [ "${PROTO}" == "IPv6" ] ; then IP_DST=${IPv6_DST} ip netns exec ${NS3} bash -c \ - "nc -6 -l -s ${IPv6_DST} -p 9000 > ${TMPFILE} &" + "nc -6 -l -p 9000 > ${TMPFILE} &" RET=$? else echo " test_gso: unknown PROTO: ${PROTO}" diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py index 15a666329a34df435dad7021845c0cbb377fb615..1afa22c88e42a85e49a299eb1e0ff72f8fbbae3d 100755 --- a/tools/testing/selftests/bpf/test_offload.py +++ b/tools/testing/selftests/bpf/test_offload.py @@ -22,6 +22,7 @@ import os import pprint import random import re +import stat import string import struct import subprocess @@ -311,7 +312,11 @@ class DebugfsDir: for f in out.split(): if f == "ports": continue + p = os.path.join(path, f) + if not os.stat(p).st_mode & stat.S_IRUSR: + continue + if os.path.isfile(p): _, out = cmd('cat %s/%s' % (path, f)) dfs[f] = out.strip() diff --git a/tools/testing/selftests/bpf/test_tc_edt.sh b/tools/testing/selftests/bpf/test_tc_edt.sh index f38567ef694b6e34cae650cad1676e1fe7391d6e..daa7d1b8d30925ea09a1357cd5cecae709bb7a39 100755 --- a/tools/testing/selftests/bpf/test_tc_edt.sh +++ b/tools/testing/selftests/bpf/test_tc_edt.sh @@ -59,7 +59,7 @@ ip netns exec ${NS_SRC} tc filter add dev veth_src egress \ # start the listener ip netns exec ${NS_DST} bash -c \ - "nc -4 -l -s ${IP_DST} -p 9000 >/dev/null &" + "nc -4 -l -p 9000 >/dev/null &" declare -i NC_PID=$! sleep 1 diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index b35da375530afb1a3d2166aeac07c49f4cff11a7..409c1fa75e03575c2c04736b325b0484ae8fd65a 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -1,4 +1,5 @@ /s390x/sync_regs_test +/s390x/memop /x86_64/cr4_cpuid_sync_test /x86_64/evmcs_test /x86_64/hyperv_cpuid @@ -9,6 +10,7 @@ /x86_64/state_test /x86_64/sync_regs_test /x86_64/vmx_close_while_nested_test +/x86_64/vmx_dirty_log_test /x86_64/vmx_set_nested_state_test /x86_64/vmx_tsc_adjust_test /clear_dirty_log_test diff --git a/tools/testing/selftests/kvm/include/x86_64/vmx.h b/tools/testing/selftests/kvm/include/x86_64/vmx.h index 6ae5a47fe067dd0a7fb0e753ca766ed8c0a745a5..f52e0ba84fedb0fe364998bda8da1e9d8f21ee1f 100644 --- a/tools/testing/selftests/kvm/include/x86_64/vmx.h +++ b/tools/testing/selftests/kvm/include/x86_64/vmx.h @@ -580,6 +580,8 @@ bool prepare_for_vmx_operation(struct vmx_pages *vmx); void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp); bool load_vmcs(struct vmx_pages *vmx); +void nested_vmx_check_supported(void); + void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr, uint32_t eptp_memslot); void nested_map(struct vmx_pages *vmx, struct kvm_vm *vm, diff --git a/tools/testing/selftests/kvm/lib/x86_64/vmx.c b/tools/testing/selftests/kvm/lib/x86_64/vmx.c index fab8f6b0bf52a6d9a68d4d4125c9897123b9e48d..f6ec97b7eaef67b6cbce47f1d6a7fa0fb3ef1e0e 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/vmx.c +++ b/tools/testing/selftests/kvm/lib/x86_64/vmx.c @@ -376,6 +376,16 @@ void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp) init_vmcs_guest_state(guest_rip, guest_rsp); } +void nested_vmx_check_supported(void) +{ + struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); + + if (!(entry->ecx & CPUID_VMX)) { + fprintf(stderr, "nested VMX not enabled, skipping test\n"); + exit(KSFT_SKIP); + } +} + void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr, uint32_t eptp_memslot) { diff --git a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c index 11c2a70a7b87a5df60772eefee2284be3376eaf1..5c82242562943fe36e14ff3bb24a4745a16ce76b 100644 --- a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c +++ b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c @@ -22,18 +22,19 @@ #define VCPU_ID 5 +#define UCALL_PIO_PORT ((uint16_t)0x1000) + +/* + * ucall is embedded here to protect against compiler reshuffling registers + * before calling a function. In this test we only need to get KVM_EXIT_IO + * vmexit and preserve RBX, no additional information is needed. + */ void guest_code(void) { - /* - * use a callee-save register, otherwise the compiler - * saves it around the call to GUEST_SYNC. - */ - register u32 stage asm("rbx"); - for (;;) { - GUEST_SYNC(0); - stage++; - asm volatile ("" : : "r" (stage)); - } + asm volatile("1: in %[port], %%al\n" + "add $0x1, %%rbx\n" + "jmp 1b" + : : [port] "d" (UCALL_PIO_PORT) : "rax", "rbx"); } static void compare_regs(struct kvm_regs *left, struct kvm_regs *right) diff --git a/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c b/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c index 3b0ffe01dacd06e986bb1a66999af64ef5a75dae..5dfb53546a266d3681e32d7e2fd1fcb42fb3166f 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c @@ -53,12 +53,8 @@ static void l1_guest_code(struct vmx_pages *vmx_pages) int main(int argc, char *argv[]) { vm_vaddr_t vmx_pages_gva; - struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); - if (!(entry->ecx & CPUID_VMX)) { - fprintf(stderr, "nested VMX not enabled, skipping test\n"); - exit(KSFT_SKIP); - } + nested_vmx_check_supported(); vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code); vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); diff --git a/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c b/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c index 0bca1cfe2c1e237d72f6017b58f3987947098a28..a223a640125843fde425c0a7b530b4f7c094500c 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c @@ -78,6 +78,8 @@ int main(int argc, char *argv[]) struct ucall uc; bool done = false; + nested_vmx_check_supported(); + /* Create VM */ vm = vm_create_default(VCPU_ID, 0, l1_guest_code); vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); diff --git a/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c b/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c index 853e370e8a3942c559925f37d0387e68a81aeef0..9ef7fab39d4878b937a435dce9fa7859dc687f39 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c @@ -224,7 +224,6 @@ int main(int argc, char *argv[]) { struct kvm_vm *vm; struct kvm_nested_state state; - struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); have_evmcs = kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS); @@ -237,10 +236,7 @@ int main(int argc, char *argv[]) * AMD currently does not implement set_nested_state, so for now we * just early out. */ - if (!(entry->ecx & CPUID_VMX)) { - fprintf(stderr, "nested VMX not enabled, skipping test\n"); - exit(KSFT_SKIP); - } + nested_vmx_check_supported(); vm = vm_create_default(VCPU_ID, 0, 0); @@ -271,12 +267,7 @@ int main(int argc, char *argv[]) state.flags = KVM_STATE_NESTED_RUN_PENDING; test_nested_state_expect_einval(vm, &state); - /* - * TODO: When SVM support is added for KVM_SET_NESTED_STATE - * add tests here to support it like VMX. - */ - if (entry->ecx & CPUID_VMX) - test_vmx_nested_state(vm); + test_vmx_nested_state(vm); kvm_vm_free(vm); return 0; diff --git a/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c index f36c10eba71edc6b4b1786d4976a4a11e774c20b..5590fd2bcf87d450e22946ab378620d043094533 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c @@ -128,12 +128,8 @@ static void report(int64_t val) int main(int argc, char *argv[]) { vm_vaddr_t vmx_pages_gva; - struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); - if (!(entry->ecx & CPUID_VMX)) { - fprintf(stderr, "nested VMX not enabled, skipping test\n"); - exit(KSFT_SKIP); - } + nested_vmx_check_supported(); vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code); vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh index c4ba0ff4a53faefa225ef847fcb544f6cea6510d..76c1897e6352fefd9f5962549a7ac937c249b883 100755 --- a/tools/testing/selftests/net/fib_tests.sh +++ b/tools/testing/selftests/net/fib_tests.sh @@ -1438,6 +1438,27 @@ ipv4_addr_metric_test() fi log_test $rc 0 "Prefix route with metric on link up" + # explicitly check for metric changes on edge scenarios + run_cmd "$IP addr flush dev dummy2" + run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259" + run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260" + rc=$? + if [ $rc -eq 0 ]; then + check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260" + rc=$? + fi + log_test $rc 0 "Modify metric of .0/24 address" + + run_cmd "$IP addr flush dev dummy2" + run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260" + run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 261" + rc=$? + if [ $rc -eq 0 ]; then + check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261" + rc=$? + fi + log_test $rc 0 "Modify metric of address with peer route" + $IP li del dummy1 $IP li del dummy2 cleanup diff --git a/tools/testing/selftests/net/l2tp.sh b/tools/testing/selftests/net/l2tp.sh old mode 100644 new mode 100755 diff --git a/tools/testing/selftests/net/reuseport_dualstack.c b/tools/testing/selftests/net/reuseport_dualstack.c index fe3230c5598639f30586142fac2f1eda851c7c3d..fb7a59ed759ebbef223bfe92e85acd33c0b4c597 100644 --- a/tools/testing/selftests/net/reuseport_dualstack.c +++ b/tools/testing/selftests/net/reuseport_dualstack.c @@ -129,7 +129,7 @@ static void test(int *rcv_fds, int count, int proto) { struct epoll_event ev; int epfd, i, test_fd; - uint16_t test_family; + int test_family; socklen_t len; epfd = epoll_create(1); @@ -146,6 +146,7 @@ static void test(int *rcv_fds, int count, int proto) send_from_v4(proto); test_fd = receive_once(epfd, proto); + len = sizeof(test_family); if (getsockopt(test_fd, SOL_SOCKET, SO_DOMAIN, &test_family, &len)) error(1, errno, "failed to read socket domain"); if (test_family != AF_INET) diff --git a/tools/testing/selftests/vm/gup_benchmark.c b/tools/testing/selftests/vm/gup_benchmark.c index c0534e298b5128d9bc2800abb5b59d7d5379f75e..cb3fc09645c482a526e2817250469611a5697010 100644 --- a/tools/testing/selftests/vm/gup_benchmark.c +++ b/tools/testing/selftests/vm/gup_benchmark.c @@ -37,7 +37,7 @@ int main(int argc, char **argv) char *file = "/dev/zero"; char *p; - while ((opt = getopt(argc, argv, "m:r:n:f:tTLUSH")) != -1) { + while ((opt = getopt(argc, argv, "m:r:n:f:tTLUwSH")) != -1) { switch (opt) { case 'm': size = atoi(optarg) * MB; diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.c b/tools/usb/usbip/libsrc/usbip_device_driver.c index 051d7d3f443b4f6663d38b5c190f9293ac51f359..927a151fa9aa9e52c5c721f20c34d1682575b17f 100644 --- a/tools/usb/usbip/libsrc/usbip_device_driver.c +++ b/tools/usb/usbip/libsrc/usbip_device_driver.c @@ -69,7 +69,7 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev) FILE *fd = NULL; struct udev_device *plat; const char *speed; - int ret = 0; + size_t ret; plat = udev_device_get_parent(sdev); path = udev_device_get_syspath(plat); @@ -79,8 +79,10 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev) if (!fd) return -1; ret = fread((char *) &descr, sizeof(descr), 1, fd); - if (ret < 0) + if (ret != 1) { + err("Cannot read vudc device descr file: %s", strerror(errno)); goto err; + } fclose(fd); copy_descr_attr(dev, &descr, bDeviceClass); diff --git a/tools/virtio/crypto/hash.h b/tools/virtio/crypto/hash.h new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h index f91aeb5fe57162f1fba03d93d26903fe14200a8f..8f41cd6bd5c088d9c9d0828331a139cf2cc94316 100644 --- a/tools/virtio/linux/dma-mapping.h +++ b/tools/virtio/linux/dma-mapping.h @@ -29,4 +29,6 @@ enum dma_data_direction { #define dma_unmap_single(...) do { } while (0) #define dma_unmap_page(...) do { } while (0) +#define dma_max_mapping_size(...) SIZE_MAX + #endif diff --git a/tools/virtio/xen/xen.h b/tools/virtio/xen/xen.h new file mode 100644 index 0000000000000000000000000000000000000000..f569387d1403e5ba70b5a72d2ae4ef1be5aaceae --- /dev/null +++ b/tools/virtio/xen/xen.h @@ -0,0 +1,6 @@ +#ifndef XEN_XEN_STUB_H +#define XEN_XEN_STUB_H + +#define xen_domain() 0 + +#endif diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c index 362a01886bab9ef64ca89b61de1ff93ddf26e1bb..8731dfeced8b7ea4f2bb19e19d833330914be2d8 100644 --- a/virt/kvm/arm/pmu.c +++ b/virt/kvm/arm/pmu.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -146,8 +147,7 @@ u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx) if (kvm_pmu_pmc_is_chained(pmc) && kvm_pmu_idx_is_high_counter(select_idx)) counter = upper_32_bits(counter); - - else if (!kvm_pmu_idx_is_64bit(vcpu, select_idx)) + else if (select_idx != ARMV8_PMU_CYCLE_IDX) counter = lower_32_bits(counter); return counter; @@ -193,7 +193,7 @@ static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc) */ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc) { - u64 counter, reg; + u64 counter, reg, val; pmc = kvm_pmu_get_canonical_pmc(pmc); if (!pmc->perf_event) @@ -201,16 +201,19 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc) counter = kvm_pmu_get_pair_counter_value(vcpu, pmc); - if (kvm_pmu_pmc_is_chained(pmc)) { - reg = PMEVCNTR0_EL0 + pmc->idx; - __vcpu_sys_reg(vcpu, reg) = lower_32_bits(counter); - __vcpu_sys_reg(vcpu, reg + 1) = upper_32_bits(counter); + if (pmc->idx == ARMV8_PMU_CYCLE_IDX) { + reg = PMCCNTR_EL0; + val = counter; } else { - reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX) - ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx; - __vcpu_sys_reg(vcpu, reg) = lower_32_bits(counter); + reg = PMEVCNTR0_EL0 + pmc->idx; + val = lower_32_bits(counter); } + __vcpu_sys_reg(vcpu, reg) = val; + + if (kvm_pmu_pmc_is_chained(pmc)) + __vcpu_sys_reg(vcpu, reg + 1) = upper_32_bits(counter); + kvm_pmu_release_perf_event(pmc); } @@ -440,8 +443,25 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event, struct pt_regs *regs) { struct kvm_pmc *pmc = perf_event->overflow_handler_context; + struct arm_pmu *cpu_pmu = to_arm_pmu(perf_event->pmu); struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc); int idx = pmc->idx; + u64 period; + + cpu_pmu->pmu.stop(perf_event, PERF_EF_UPDATE); + + /* + * Reset the sample period to the architectural limit, + * i.e. the point where the counter overflows. + */ + period = -(local64_read(&perf_event->count)); + + if (!kvm_pmu_idx_is_64bit(vcpu, pmc->idx)) + period &= GENMASK(31, 0); + + local64_set(&perf_event->hw.period_left, 0); + perf_event->attr.sample_period = period; + perf_event->hw.sample_period = period; __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx); @@ -449,6 +469,8 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event, kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu); kvm_vcpu_kick(vcpu); } + + cpu_pmu->pmu.start(perf_event, PERF_EF_RELOAD); } /** @@ -567,12 +589,12 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx) * high counter. */ attr.sample_period = (-counter) & GENMASK(63, 0); + if (kvm_pmu_counter_is_enabled(vcpu, pmc->idx + 1)) + attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED; + event = perf_event_create_kernel_counter(&attr, -1, current, kvm_pmu_perf_overflow, pmc + 1); - - if (kvm_pmu_counter_is_enabled(vcpu, pmc->idx + 1)) - attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED; } else { /* The initial sample period (overflow count) of an event. */ if (kvm_pmu_idx_is_64bit(vcpu, pmc->idx)) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index fd68fbe0a75d2f24594c2ab0a89ba7923b12e3eb..d6f0696d98efe4738b470e4a92ca24ca33d54d61 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -627,8 +627,9 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd) static struct kvm *kvm_create_vm(unsigned long type) { - int r, i; struct kvm *kvm = kvm_arch_alloc_vm(); + int r = -ENOMEM; + int i; if (!kvm) return ERR_PTR(-ENOMEM); @@ -640,44 +641,45 @@ static struct kvm *kvm_create_vm(unsigned long type) mutex_init(&kvm->lock); mutex_init(&kvm->irq_lock); mutex_init(&kvm->slots_lock); - refcount_set(&kvm->users_count, 1); INIT_LIST_HEAD(&kvm->devices); - r = kvm_arch_init_vm(kvm, type); - if (r) - goto out_err_no_disable; - - r = hardware_enable_all(); - if (r) - goto out_err_no_disable; - -#ifdef CONFIG_HAVE_KVM_IRQFD - INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list); -#endif - BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX); - r = -ENOMEM; for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { struct kvm_memslots *slots = kvm_alloc_memslots(); + if (!slots) - goto out_err_no_srcu; + goto out_err_no_arch_destroy_vm; /* Generations must be different for each address space. */ slots->generation = i; rcu_assign_pointer(kvm->memslots[i], slots); } - if (init_srcu_struct(&kvm->srcu)) - goto out_err_no_srcu; - if (init_srcu_struct(&kvm->irq_srcu)) - goto out_err_no_irq_srcu; for (i = 0; i < KVM_NR_BUSES; i++) { rcu_assign_pointer(kvm->buses[i], kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL_ACCOUNT)); if (!kvm->buses[i]) - goto out_err; + goto out_err_no_arch_destroy_vm; } + refcount_set(&kvm->users_count, 1); + r = kvm_arch_init_vm(kvm, type); + if (r) + goto out_err_no_arch_destroy_vm; + + r = hardware_enable_all(); + if (r) + goto out_err_no_disable; + +#ifdef CONFIG_HAVE_KVM_IRQFD + INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list); +#endif + + if (init_srcu_struct(&kvm->srcu)) + goto out_err_no_srcu; + if (init_srcu_struct(&kvm->irq_srcu)) + goto out_err_no_irq_srcu; + r = kvm_init_mmu_notifier(kvm); if (r) goto out_err; @@ -697,7 +699,9 @@ static struct kvm *kvm_create_vm(unsigned long type) out_err_no_srcu: hardware_disable_all(); out_err_no_disable: - refcount_set(&kvm->users_count, 0); + kvm_arch_destroy_vm(kvm); + WARN_ON_ONCE(!refcount_dec_and_test(&kvm->users_count)); +out_err_no_arch_destroy_vm: for (i = 0; i < KVM_NR_BUSES; i++) kfree(kvm_get_bus(kvm, i)); for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) @@ -2360,20 +2364,23 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) kvm_arch_vcpu_unblocking(vcpu); block_ns = ktime_to_ns(cur) - ktime_to_ns(start); - if (!vcpu_valid_wakeup(vcpu)) - shrink_halt_poll_ns(vcpu); - else if (halt_poll_ns) { - if (block_ns <= vcpu->halt_poll_ns) - ; - /* we had a long block, shrink polling */ - else if (vcpu->halt_poll_ns && block_ns > halt_poll_ns) + if (!kvm_arch_no_poll(vcpu)) { + if (!vcpu_valid_wakeup(vcpu)) { shrink_halt_poll_ns(vcpu); - /* we had a short halt and our poll time is too small */ - else if (vcpu->halt_poll_ns < halt_poll_ns && - block_ns < halt_poll_ns) - grow_halt_poll_ns(vcpu); - } else - vcpu->halt_poll_ns = 0; + } else if (halt_poll_ns) { + if (block_ns <= vcpu->halt_poll_ns) + ; + /* we had a long block, shrink polling */ + else if (vcpu->halt_poll_ns && block_ns > halt_poll_ns) + shrink_halt_poll_ns(vcpu); + /* we had a short halt and our poll time is too small */ + else if (vcpu->halt_poll_ns < halt_poll_ns && + block_ns < halt_poll_ns) + grow_halt_poll_ns(vcpu); + } else { + vcpu->halt_poll_ns = 0; + } + } trace_kvm_vcpu_wakeup(block_ns, waited, vcpu_valid_wakeup(vcpu)); kvm_arch_vcpu_block_finish(vcpu);