diff options
-rw-r--r-- | 0000_README | 16 | ||||
-rw-r--r-- | 1000_linux-6.9.1.patch | 286 | ||||
-rw-r--r-- | 1001_linux-6.9.2.patch | 1480 | ||||
-rw-r--r-- | 1002_linux-6.9.3.patch | 18354 | ||||
-rw-r--r-- | 1003_linux-6.9.4.patch | 15797 |
5 files changed, 35933 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 887cea4c..f824f87c 100644 --- a/0000_README +++ b/0000_README @@ -43,6 +43,22 @@ EXPERIMENTAL Individual Patch Descriptions: -------------------------------------------------------------------------- +Patch: 1000_linux-6.9.1.patch +From: https://www.kernel.org +Desc: Linux 6.9.1 + +Patch: 1001_linux-6.9.2.patch +From: https://www.kernel.org +Desc: Linux 6.9.2 + +Patch: 1002_linux-6.9.3.patch +From: https://www.kernel.org +Desc: Linux 6.9.3 + +Patch: 1003_linux-6.9.4.patch +From: https://www.kernel.org +Desc: Linux 6.9.4 + Patch: 1510_fs-enable-link-security-restrictions-by-default.patch From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/ Desc: Enable link security restrictions by default. diff --git a/1000_linux-6.9.1.patch b/1000_linux-6.9.1.patch new file mode 100644 index 00000000..277d2283 --- /dev/null +++ b/1000_linux-6.9.1.patch @@ -0,0 +1,286 @@ +diff --git a/Makefile b/Makefile +index 967e97878ecdf..a7045435151e6 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 9 +-SUBLEVEL = 0 ++SUBLEVEL = 1 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c +index c095a2c8f6595..39935071174a3 100644 +--- a/drivers/dma/idxd/cdev.c ++++ b/drivers/dma/idxd/cdev.c +@@ -400,6 +400,18 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma) + int rc; + + dev_dbg(&pdev->dev, "%s called\n", __func__); ++ ++ /* ++ * Due to an erratum in some of the devices supported by the driver, ++ * direct user submission to the device can be unsafe. ++ * (See the INTEL-SA-01084 security advisory) ++ * ++ * For the devices that exhibit this behavior, require that the user ++ * has CAP_SYS_RAWIO capabilities. ++ */ ++ if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO)) ++ return -EPERM; ++ + rc = check_vma(wq, vma, __func__); + if (rc < 0) + return rc; +@@ -414,6 +426,70 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma) + vma->vm_page_prot); + } + ++static int idxd_submit_user_descriptor(struct idxd_user_context *ctx, ++ struct dsa_hw_desc __user *udesc) ++{ ++ struct idxd_wq *wq = ctx->wq; ++ struct idxd_dev *idxd_dev = &wq->idxd->idxd_dev; ++ const uint64_t comp_addr_align = is_dsa_dev(idxd_dev) ? 0x20 : 0x40; ++ void __iomem *portal = idxd_wq_portal_addr(wq); ++ struct dsa_hw_desc descriptor __aligned(64); ++ int rc; ++ ++ rc = copy_from_user(&descriptor, udesc, sizeof(descriptor)); ++ if (rc) ++ return -EFAULT; ++ ++ /* ++ * DSA devices are capable of indirect ("batch") command submission. ++ * On devices where direct user submissions are not safe, we cannot ++ * allow this since there is no good way for us to verify these ++ * indirect commands. ++ */ ++ if (is_dsa_dev(idxd_dev) && descriptor.opcode == DSA_OPCODE_BATCH && ++ !wq->idxd->user_submission_safe) ++ return -EINVAL; ++ /* ++ * As per the programming specification, the completion address must be ++ * aligned to 32 or 64 bytes. If this is violated the hardware ++ * engine can get very confused (security issue). ++ */ ++ if (!IS_ALIGNED(descriptor.completion_addr, comp_addr_align)) ++ return -EINVAL; ++ ++ if (wq_dedicated(wq)) ++ iosubmit_cmds512(portal, &descriptor, 1); ++ else { ++ descriptor.priv = 0; ++ descriptor.pasid = ctx->pasid; ++ rc = idxd_enqcmds(wq, portal, &descriptor); ++ if (rc < 0) ++ return rc; ++ } ++ ++ return 0; ++} ++ ++static ssize_t idxd_cdev_write(struct file *filp, const char __user *buf, size_t len, ++ loff_t *unused) ++{ ++ struct dsa_hw_desc __user *udesc = (struct dsa_hw_desc __user *)buf; ++ struct idxd_user_context *ctx = filp->private_data; ++ ssize_t written = 0; ++ int i; ++ ++ for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) { ++ int rc = idxd_submit_user_descriptor(ctx, udesc + i); ++ ++ if (rc) ++ return written ? written : rc; ++ ++ written += sizeof(struct dsa_hw_desc); ++ } ++ ++ return written; ++} ++ + static __poll_t idxd_cdev_poll(struct file *filp, + struct poll_table_struct *wait) + { +@@ -436,6 +512,7 @@ static const struct file_operations idxd_cdev_fops = { + .open = idxd_cdev_open, + .release = idxd_cdev_release, + .mmap = idxd_cdev_mmap, ++ .write = idxd_cdev_write, + .poll = idxd_cdev_poll, + }; + +diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h +index 7b98944135eb4..868b724a3b75b 100644 +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -288,6 +288,7 @@ struct idxd_driver_data { + int evl_cr_off; + int cr_status_off; + int cr_result_off; ++ bool user_submission_safe; + load_device_defaults_fn_t load_device_defaults; + }; + +@@ -374,6 +375,8 @@ struct idxd_device { + + struct dentry *dbgfs_dir; + struct dentry *dbgfs_evl_file; ++ ++ bool user_submission_safe; + }; + + static inline unsigned int evl_ent_size(struct idxd_device *idxd) +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index 264c4e47d7cca..a7295943fa223 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -47,6 +47,7 @@ static struct idxd_driver_data idxd_driver_data[] = { + .align = 32, + .dev_type = &dsa_device_type, + .evl_cr_off = offsetof(struct dsa_evl_entry, cr), ++ .user_submission_safe = false, /* See INTEL-SA-01084 security advisory */ + .cr_status_off = offsetof(struct dsa_completion_record, status), + .cr_result_off = offsetof(struct dsa_completion_record, result), + }, +@@ -57,6 +58,7 @@ static struct idxd_driver_data idxd_driver_data[] = { + .align = 64, + .dev_type = &iax_device_type, + .evl_cr_off = offsetof(struct iax_evl_entry, cr), ++ .user_submission_safe = false, /* See INTEL-SA-01084 security advisory */ + .cr_status_off = offsetof(struct iax_completion_record, status), + .cr_result_off = offsetof(struct iax_completion_record, error_code), + .load_device_defaults = idxd_load_iaa_device_defaults, +@@ -774,6 +776,8 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + dev_info(&pdev->dev, "Intel(R) Accelerator Device (v%x)\n", + idxd->hw.version); + ++ idxd->user_submission_safe = data->user_submission_safe; ++ + return 0; + + err_dev_register: +diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h +index 315c004f58e47..e16dbf9ab324c 100644 +--- a/drivers/dma/idxd/registers.h ++++ b/drivers/dma/idxd/registers.h +@@ -6,9 +6,6 @@ + #include <uapi/linux/idxd.h> + + /* PCI Config */ +-#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25 +-#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe +- + #define DEVICE_VERSION_1 0x100 + #define DEVICE_VERSION_2 0x200 + +diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c +index 7f28f01be672b..f706eae0e76b1 100644 +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -1197,12 +1197,35 @@ static ssize_t wq_enqcmds_retries_store(struct device *dev, struct device_attrib + static struct device_attribute dev_attr_wq_enqcmds_retries = + __ATTR(enqcmds_retries, 0644, wq_enqcmds_retries_show, wq_enqcmds_retries_store); + ++static ssize_t op_cap_show_common(struct device *dev, char *buf, unsigned long *opcap_bmap) ++{ ++ ssize_t pos; ++ int i; ++ ++ pos = 0; ++ for (i = IDXD_MAX_OPCAP_BITS/64 - 1; i >= 0; i--) { ++ unsigned long val = opcap_bmap[i]; ++ ++ /* On systems where direct user submissions are not safe, we need to clear out ++ * the BATCH capability from the capability mask in sysfs since we cannot support ++ * that command on such systems. ++ */ ++ if (i == DSA_OPCODE_BATCH/64 && !confdev_to_idxd(dev)->user_submission_safe) ++ clear_bit(DSA_OPCODE_BATCH % 64, &val); ++ ++ pos += sysfs_emit_at(buf, pos, "%*pb", 64, &val); ++ pos += sysfs_emit_at(buf, pos, "%c", i == 0 ? '\n' : ','); ++ } ++ ++ return pos; ++} ++ + static ssize_t wq_op_config_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct idxd_wq *wq = confdev_to_wq(dev); + +- return sysfs_emit(buf, "%*pb\n", IDXD_MAX_OPCAP_BITS, wq->opcap_bmap); ++ return op_cap_show_common(dev, buf, wq->opcap_bmap); + } + + static int idxd_verify_supported_opcap(struct idxd_device *idxd, unsigned long *opmask) +@@ -1455,7 +1478,7 @@ static ssize_t op_cap_show(struct device *dev, + { + struct idxd_device *idxd = confdev_to_idxd(dev); + +- return sysfs_emit(buf, "%*pb\n", IDXD_MAX_OPCAP_BITS, idxd->opcap_bmap); ++ return op_cap_show_common(dev, buf, idxd->opcap_bmap); + } + static DEVICE_ATTR_RO(op_cap); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +index 3709d18da0e6b..075d04ba3ef28 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +@@ -1657,6 +1657,10 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, + #endif + + const struct ieee80211_ops mt7915_ops = { ++ .add_chanctx = ieee80211_emulate_add_chanctx, ++ .remove_chanctx = ieee80211_emulate_remove_chanctx, ++ .change_chanctx = ieee80211_emulate_change_chanctx, ++ .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, + .tx = mt7915_tx, + .start = mt7915_start, + .stop = mt7915_stop, +diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c +index cb5b7f865d585..e727941f589de 100644 +--- a/drivers/vfio/pci/vfio_pci.c ++++ b/drivers/vfio/pci/vfio_pci.c +@@ -71,6 +71,8 @@ static bool vfio_pci_dev_in_denylist(struct pci_dev *pdev) + case PCI_DEVICE_ID_INTEL_QAT_C62X_VF: + case PCI_DEVICE_ID_INTEL_QAT_DH895XCC: + case PCI_DEVICE_ID_INTEL_QAT_DH895XCC_VF: ++ case PCI_DEVICE_ID_INTEL_DSA_SPR0: ++ case PCI_DEVICE_ID_INTEL_IAX_SPR0: + return true; + default: + return false; +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index c547d1d4feb1e..4beb29907c2bd 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -2687,8 +2687,10 @@ + #define PCI_DEVICE_ID_INTEL_I960 0x0960 + #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 + #define PCI_DEVICE_ID_INTEL_HDA_HSW_0 0x0a0c ++#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25 + #define PCI_DEVICE_ID_INTEL_HDA_HSW_2 0x0c0c + #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 ++#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe + #define PCI_DEVICE_ID_INTEL_HDA_HSW_3 0x0d0c + #define PCI_DEVICE_ID_INTEL_HDA_BYT 0x0f04 + #define PCI_DEVICE_ID_INTEL_SST_BYT 0x0f28 +diff --git a/security/keys/key.c b/security/keys/key.c +index 5607900383298..0aa5f01d16ffb 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -463,7 +463,8 @@ static int __key_instantiate_and_link(struct key *key, + if (authkey) + key_invalidate(authkey); + +- key_set_expiry(key, prep->expiry); ++ if (prep->expiry != TIME64_MAX) ++ key_set_expiry(key, prep->expiry); + } + } + diff --git a/1001_linux-6.9.2.patch b/1001_linux-6.9.2.patch new file mode 100644 index 00000000..0b2b2476 --- /dev/null +++ b/1001_linux-6.9.2.patch @@ -0,0 +1,1480 @@ +diff --git a/Documentation/ABI/stable/sysfs-block b/Documentation/ABI/stable/sysfs-block +index 1fe9a553c37b7..f0025d1c3d5ac 100644 +--- a/Documentation/ABI/stable/sysfs-block ++++ b/Documentation/ABI/stable/sysfs-block +@@ -101,6 +101,16 @@ Description: + devices that support receiving integrity metadata. + + ++What: /sys/block/<disk>/partscan ++Date: May 2024 ++Contact: Christoph Hellwig <hch@lst.de> ++Description: ++ The /sys/block/<disk>/partscan files reports if partition ++ scanning is enabled for the disk. It returns "1" if partition ++ scanning is enabled, or "0" if not. The value type is a 32-bit ++ unsigned integer, but only "0" and "1" are valid values. ++ ++ + What: /sys/block/<disk>/<partition>/alignment_offset + Date: April 2009 + Contact: Martin K. Petersen <martin.petersen@oracle.com> +diff --git a/Documentation/admin-guide/hw-vuln/core-scheduling.rst b/Documentation/admin-guide/hw-vuln/core-scheduling.rst +index cf1eeefdfc32f..a92e10ec402e7 100644 +--- a/Documentation/admin-guide/hw-vuln/core-scheduling.rst ++++ b/Documentation/admin-guide/hw-vuln/core-scheduling.rst +@@ -67,8 +67,8 @@ arg4: + will be performed for all tasks in the task group of ``pid``. + + arg5: +- userspace pointer to an unsigned long for storing the cookie returned by +- ``PR_SCHED_CORE_GET`` command. Should be 0 for all other commands. ++ userspace pointer to an unsigned long long for storing the cookie returned ++ by ``PR_SCHED_CORE_GET`` command. Should be 0 for all other commands. + + In order for a process to push a cookie to, or pull a cookie from a process, it + is required to have the ptrace access mode: `PTRACE_MODE_READ_REALCREDS` to the +diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst +index 6fce035fdbf5c..7daf1a95f9cb4 100644 +--- a/Documentation/admin-guide/mm/damon/usage.rst ++++ b/Documentation/admin-guide/mm/damon/usage.rst +@@ -153,7 +153,7 @@ Users can write below commands for the kdamond to the ``state`` file. + - ``clear_schemes_tried_regions``: Clear the DAMON-based operating scheme + action tried regions directory for each DAMON-based operation scheme of the + kdamond. +-- ``update_schemes_effective_bytes``: Update the contents of ++- ``update_schemes_effective_quotas``: Update the contents of + ``effective_bytes`` files for each DAMON-based operation scheme of the + kdamond. For more details, refer to :ref:`quotas directory <sysfs_quotas>`. + +@@ -342,7 +342,7 @@ Based on the user-specified :ref:`goal <sysfs_schemes_quota_goals>`, the + effective size quota is further adjusted. Reading ``effective_bytes`` returns + the current effective size quota. The file is not updated in real time, so + users should ask DAMON sysfs interface to update the content of the file for +-the stats by writing a special keyword, ``update_schemes_effective_bytes`` to ++the stats by writing a special keyword, ``update_schemes_effective_quotas`` to + the relevant ``kdamonds/<N>/state`` file. + + Under ``weights`` directory, three files (``sz_permil``, +@@ -434,7 +434,7 @@ pages of all memory cgroups except ``/having_care_already``.:: + # # further filter out all cgroups except one at '/having_care_already' + echo memcg > 1/type + echo /having_care_already > 1/memcg_path +- echo N > 1/matching ++ echo Y > 1/matching + + Note that ``anon`` and ``memcg`` filters are currently supported only when + ``paddr`` :ref:`implementation <sysfs_context>` is being used. +diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py +index abe7680883771..6387624423363 100755 +--- a/Documentation/sphinx/kernel_include.py ++++ b/Documentation/sphinx/kernel_include.py +@@ -97,7 +97,6 @@ class KernelInclude(Include): + # HINT: this is the only line I had to change / commented out: + #path = utils.relative_path(None, path) + +- path = nodes.reprunicode(path) + encoding = self.options.get( + 'encoding', self.state.document.settings.input_encoding) + e_handler=self.state.document.settings.input_encoding_error_handler +diff --git a/Makefile b/Makefile +index a7045435151e6..8302496ee7a57 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 9 +-SUBLEVEL = 1 ++SUBLEVEL = 2 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h +index 44958ebaf626e..b77bbb67e77b0 100644 +--- a/arch/x86/include/asm/percpu.h ++++ b/arch/x86/include/asm/percpu.h +@@ -70,7 +70,7 @@ + unsigned long tcp_ptr__; \ + tcp_ptr__ = __raw_cpu_read(, this_cpu_off); \ + \ +- tcp_ptr__ += (unsigned long)(ptr); \ ++ tcp_ptr__ += (__force unsigned long)(ptr); \ + (typeof(*(ptr)) __kernel __force *)tcp_ptr__; \ + }) + #else /* CONFIG_USE_X86_SEG_SUPPORT */ +@@ -102,8 +102,8 @@ + #endif /* CONFIG_SMP */ + + #define __my_cpu_type(var) typeof(var) __percpu_seg_override +-#define __my_cpu_ptr(ptr) (__my_cpu_type(*ptr) *)(uintptr_t)(ptr) +-#define __my_cpu_var(var) (*__my_cpu_ptr(&var)) ++#define __my_cpu_ptr(ptr) (__my_cpu_type(*ptr)*)(__force uintptr_t)(ptr) ++#define __my_cpu_var(var) (*__my_cpu_ptr(&(var))) + #define __percpu_arg(x) __percpu_prefix "%" #x + #define __force_percpu_arg(x) __force_percpu_prefix "%" #x + +diff --git a/block/genhd.c b/block/genhd.c +index bb29a68e1d676..52a4521df067b 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -345,9 +345,7 @@ int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode) + struct file *file; + int ret = 0; + +- if (disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN)) +- return -EINVAL; +- if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state)) ++ if (!disk_has_partscan(disk)) + return -EINVAL; + if (disk->open_partitions) + return -EBUSY; +@@ -503,8 +501,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk, + goto out_unregister_bdi; + + /* Make sure the first partition scan will be proceed */ +- if (get_capacity(disk) && !(disk->flags & GENHD_FL_NO_PART) && +- !test_bit(GD_SUPPRESS_PART_SCAN, &disk->state)) ++ if (get_capacity(disk) && disk_has_partscan(disk)) + set_bit(GD_NEED_PART_SCAN, &disk->state); + + bdev_add(disk->part0, ddev->devt); +@@ -1047,6 +1044,12 @@ static ssize_t diskseq_show(struct device *dev, + return sprintf(buf, "%llu\n", disk->diskseq); + } + ++static ssize_t partscan_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%u\n", disk_has_partscan(dev_to_disk(dev))); ++} ++ + static DEVICE_ATTR(range, 0444, disk_range_show, NULL); + static DEVICE_ATTR(ext_range, 0444, disk_ext_range_show, NULL); + static DEVICE_ATTR(removable, 0444, disk_removable_show, NULL); +@@ -1060,6 +1063,7 @@ static DEVICE_ATTR(stat, 0444, part_stat_show, NULL); + static DEVICE_ATTR(inflight, 0444, part_inflight_show, NULL); + static DEVICE_ATTR(badblocks, 0644, disk_badblocks_show, disk_badblocks_store); + static DEVICE_ATTR(diskseq, 0444, diskseq_show, NULL); ++static DEVICE_ATTR(partscan, 0444, partscan_show, NULL); + + #ifdef CONFIG_FAIL_MAKE_REQUEST + ssize_t part_fail_show(struct device *dev, +@@ -1106,6 +1110,7 @@ static struct attribute *disk_attrs[] = { + &dev_attr_events_async.attr, + &dev_attr_events_poll_msecs.attr, + &dev_attr_diskseq.attr, ++ &dev_attr_partscan.attr, + #ifdef CONFIG_FAIL_MAKE_REQUEST + &dev_attr_fail.attr, + #endif +diff --git a/block/partitions/core.c b/block/partitions/core.c +index b11e88c82c8cf..37b5f92d07fec 100644 +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -573,10 +573,7 @@ static int blk_add_partitions(struct gendisk *disk) + struct parsed_partitions *state; + int ret = -EAGAIN, p; + +- if (disk->flags & GENHD_FL_NO_PART) +- return 0; +- +- if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state)) ++ if (!disk_has_partscan(disk)) + return 0; + + state = check_partition(disk); +diff --git a/drivers/android/binder.c b/drivers/android/binder.c +index dd6923d37931f..b21a7b246a0dc 100644 +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -5367,7 +5367,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + goto err; + break; + case BINDER_SET_MAX_THREADS: { +- int max_threads; ++ u32 max_threads; + + if (copy_from_user(&max_threads, ubuf, + sizeof(max_threads))) { +diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h +index 7270d4d222070..5b7c80b99ae86 100644 +--- a/drivers/android/binder_internal.h ++++ b/drivers/android/binder_internal.h +@@ -421,7 +421,7 @@ struct binder_proc { + struct list_head todo; + struct binder_stats stats; + struct list_head delivered_death; +- int max_threads; ++ u32 max_threads; + int requested_threads; + int requested_threads_started; + int tmp_ref; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index e3946f7b736e3..01b99471d1bbe 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -3118,6 +3118,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev) + bt_dev_err(hdev, "Failed to get fw flavor (%d)", err); + return err; + } ++ fw_flavor = (fw_flavor & 0x00000080) >> 7; + } + + mediatek = hci_get_priv(hdev); +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 2015c9fcc3c91..28166df81cf8d 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -50,7 +50,8 @@ + + #define AMD_PSTATE_TRANSITION_LATENCY 20000 + #define AMD_PSTATE_TRANSITION_DELAY 1000 +-#define AMD_PSTATE_PREFCORE_THRESHOLD 166 ++#define CPPC_HIGHEST_PERF_PERFORMANCE 196 ++#define CPPC_HIGHEST_PERF_DEFAULT 166 + + /* + * TODO: We need more time to fine tune processors with shared memory solution +@@ -290,6 +291,21 @@ static inline int amd_pstate_enable(bool enable) + return static_call(amd_pstate_enable)(enable); + } + ++static u32 amd_pstate_highest_perf_set(struct amd_cpudata *cpudata) ++{ ++ struct cpuinfo_x86 *c = &cpu_data(0); ++ ++ /* ++ * For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f, ++ * the highest performance level is set to 196. ++ * https://bugzilla.kernel.org/show_bug.cgi?id=218759 ++ */ ++ if (c->x86 == 0x19 && (c->x86_model >= 0x70 && c->x86_model <= 0x7f)) ++ return CPPC_HIGHEST_PERF_PERFORMANCE; ++ ++ return CPPC_HIGHEST_PERF_DEFAULT; ++} ++ + static int pstate_init_perf(struct amd_cpudata *cpudata) + { + u64 cap1; +@@ -306,7 +322,7 @@ static int pstate_init_perf(struct amd_cpudata *cpudata) + * the default max perf. + */ + if (cpudata->hw_prefcore) +- highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD; ++ highest_perf = amd_pstate_highest_perf_set(cpudata); + else + highest_perf = AMD_CPPC_HIGHEST_PERF(cap1); + +@@ -330,7 +346,7 @@ static int cppc_init_perf(struct amd_cpudata *cpudata) + return ret; + + if (cpudata->hw_prefcore) +- highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD; ++ highest_perf = amd_pstate_highest_perf_set(cpudata); + else + highest_perf = cppc_perf.highest_perf; + +diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +index ac41f9c0a2834..8e7b35f764e39 100644 +--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c ++++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +@@ -1055,7 +1055,12 @@ static bool setup_dsc_config( + if (!is_dsc_possible) + goto done; + +- dsc_cfg->num_slices_v = pic_height/slice_height; ++ if (slice_height > 0) { ++ dsc_cfg->num_slices_v = pic_height / slice_height; ++ } else { ++ is_dsc_possible = false; ++ goto done; ++ } + + if (target_bandwidth_kbps > 0) { + is_dsc_possible = decide_dsc_target_bpp_x16( +diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c +index c4d995f32191c..09ceb2a868764 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c +@@ -2504,8 +2504,7 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl) + EXPORT_SYMBOL(v4l2_ctrl_handler_setup); + + /* Log the control name and value */ +-static void log_ctrl(const struct v4l2_ctrl_handler *hdl, +- struct v4l2_ctrl *ctrl, ++static void log_ctrl(const struct v4l2_ctrl *ctrl, + const char *prefix, const char *colon) + { + if (ctrl->flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY)) +@@ -2515,11 +2514,7 @@ static void log_ctrl(const struct v4l2_ctrl_handler *hdl, + + pr_info("%s%s%s: ", prefix, colon, ctrl->name); + +- if (ctrl->handler != hdl) +- v4l2_ctrl_lock(ctrl); + ctrl->type_ops->log(ctrl); +- if (ctrl->handler != hdl) +- v4l2_ctrl_unlock(ctrl); + + if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE | + V4L2_CTRL_FLAG_GRABBED | +@@ -2538,7 +2533,7 @@ static void log_ctrl(const struct v4l2_ctrl_handler *hdl, + void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl, + const char *prefix) + { +- struct v4l2_ctrl_ref *ref; ++ struct v4l2_ctrl *ctrl; + const char *colon = ""; + int len; + +@@ -2550,12 +2545,9 @@ void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl, + if (len && prefix[len - 1] != ' ') + colon = ": "; + mutex_lock(hdl->lock); +- list_for_each_entry(ref, &hdl->ctrl_refs, node) { +- if (ref->from_other_dev || +- (ref->ctrl->flags & V4L2_CTRL_FLAG_DISABLED)) +- continue; +- log_ctrl(hdl, ref->ctrl, prefix, colon); +- } ++ list_for_each_entry(ctrl, &hdl->ctrls, node) ++ if (!(ctrl->flags & V4L2_CTRL_FLAG_DISABLED)) ++ log_ctrl(ctrl, prefix, colon); + mutex_unlock(hdl->lock); + } + EXPORT_SYMBOL(v4l2_ctrl_handler_log_status); +diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c +index 502518cdb4618..6453c92f0fa7c 100644 +--- a/drivers/net/ethernet/micrel/ks8851_common.c ++++ b/drivers/net/ethernet/micrel/ks8851_common.c +@@ -328,7 +328,6 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) + { + struct ks8851_net *ks = _ks; + struct sk_buff_head rxq; +- unsigned handled = 0; + unsigned long flags; + unsigned int status; + struct sk_buff *skb; +@@ -336,24 +335,17 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) + ks8851_lock(ks, &flags); + + status = ks8851_rdreg16(ks, KS_ISR); ++ ks8851_wrreg16(ks, KS_ISR, status); + + netif_dbg(ks, intr, ks->netdev, + "%s: status 0x%04x\n", __func__, status); + +- if (status & IRQ_LCI) +- handled |= IRQ_LCI; +- + if (status & IRQ_LDI) { + u16 pmecr = ks8851_rdreg16(ks, KS_PMECR); + pmecr &= ~PMECR_WKEVT_MASK; + ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); +- +- handled |= IRQ_LDI; + } + +- if (status & IRQ_RXPSI) +- handled |= IRQ_RXPSI; +- + if (status & IRQ_TXI) { + unsigned short tx_space = ks8851_rdreg16(ks, KS_TXMIR); + +@@ -365,20 +357,12 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) + if (netif_queue_stopped(ks->netdev)) + netif_wake_queue(ks->netdev); + spin_unlock(&ks->statelock); +- +- handled |= IRQ_TXI; + } + +- if (status & IRQ_RXI) +- handled |= IRQ_RXI; +- + if (status & IRQ_SPIBEI) { + netdev_err(ks->netdev, "%s: spi bus error\n", __func__); +- handled |= IRQ_SPIBEI; + } + +- ks8851_wrreg16(ks, KS_ISR, handled); +- + if (status & IRQ_RXI) { + /* the datasheet says to disable the rx interrupt during + * packet read-out, however we're masking the interrupt +diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c +index df9d767cb5242..56ede5fa02617 100644 +--- a/drivers/net/usb/ax88179_178a.c ++++ b/drivers/net/usb/ax88179_178a.c +@@ -174,6 +174,7 @@ struct ax88179_data { + u32 wol_supported; + u32 wolopts; + u8 disconnecting; ++ u8 initialized; + }; + + struct ax88179_int_data { +@@ -1673,6 +1674,18 @@ static int ax88179_reset(struct usbnet *dev) + return 0; + } + ++static int ax88179_net_reset(struct usbnet *dev) ++{ ++ struct ax88179_data *ax179_data = dev->driver_priv; ++ ++ if (ax179_data->initialized) ++ ax88179_reset(dev); ++ else ++ ax179_data->initialized = 1; ++ ++ return 0; ++} ++ + static int ax88179_stop(struct usbnet *dev) + { + u16 tmp16; +@@ -1692,6 +1705,7 @@ static const struct driver_info ax88179_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1704,6 +1718,7 @@ static const struct driver_info ax88178a_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1716,7 +1731,7 @@ static const struct driver_info cypress_GX3_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1729,7 +1744,7 @@ static const struct driver_info dlink_dub1312_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1742,7 +1757,7 @@ static const struct driver_info sitecom_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1755,7 +1770,7 @@ static const struct driver_info samsung_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1768,7 +1783,7 @@ static const struct driver_info lenovo_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1781,7 +1796,7 @@ static const struct driver_info belkin_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1794,7 +1809,7 @@ static const struct driver_info toshiba_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1807,7 +1822,7 @@ static const struct driver_info mct_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1820,7 +1835,7 @@ static const struct driver_info at_umc2000_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1833,7 +1848,7 @@ static const struct driver_info at_umc200_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +@@ -1846,7 +1861,7 @@ static const struct driver_info at_umc2000sp_info = { + .unbind = ax88179_unbind, + .status = ax88179_status, + .link_reset = ax88179_link_reset, +- .reset = ax88179_reset, ++ .reset = ax88179_net_reset, + .stop = ax88179_stop, + .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .rx_fixup = ax88179_rx_fixup, +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +index 4696d73c8971b..1b7254569a37a 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +@@ -1484,7 +1484,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) + size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX]; + u32 api_ver; + int i; +- bool load_module = false; + bool usniffer_images = false; + bool failure = true; + +@@ -1732,19 +1731,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) + goto out_unbind; + } + } else { +- load_module = true; ++ request_module_nowait("%s", op->name); + } + mutex_unlock(&iwlwifi_opmode_table_mtx); + + complete(&drv->request_firmware_complete); + +- /* +- * Load the module last so we don't block anything +- * else from proceeding if the module fails to load +- * or hangs loading. +- */ +- if (load_module) +- request_module("%s", op->name); + failure = false; + goto free; + +diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c +index a35409eda0cf2..67518291a8ad6 100644 +--- a/drivers/remoteproc/mtk_scp.c ++++ b/drivers/remoteproc/mtk_scp.c +@@ -132,7 +132,7 @@ static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp, + static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw) + { + int ret; +- size_t offset; ++ size_t buf_sz, offset; + + /* read the ipi buf addr from FW itself first */ + ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset); +@@ -144,6 +144,14 @@ static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw) + } + dev_info(scp->dev, "IPI buf addr %#010zx\n", offset); + ++ /* Make sure IPI buffer fits in the L2TCM range assigned to this core */ ++ buf_sz = sizeof(*scp->recv_buf) + sizeof(*scp->send_buf); ++ ++ if (scp->sram_size < buf_sz + offset) { ++ dev_err(scp->dev, "IPI buffer does not fit in SRAM.\n"); ++ return -EOVERFLOW; ++ } ++ + scp->recv_buf = (struct mtk_share_obj __iomem *) + (scp->sram_base + offset); + scp->send_buf = (struct mtk_share_obj __iomem *) +diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c +index 7ce7bb1640054..58ea1e1391cee 100644 +--- a/drivers/tty/serial/kgdboc.c ++++ b/drivers/tty/serial/kgdboc.c +@@ -19,6 +19,7 @@ + #include <linux/console.h> + #include <linux/vt_kern.h> + #include <linux/input.h> ++#include <linux/irq_work.h> + #include <linux/module.h> + #include <linux/platform_device.h> + #include <linux/serial_core.h> +@@ -48,6 +49,25 @@ static struct kgdb_io kgdboc_earlycon_io_ops; + static int (*earlycon_orig_exit)(struct console *con); + #endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */ + ++/* ++ * When we leave the debug trap handler we need to reset the keyboard status ++ * (since the original keyboard state gets partially clobbered by kdb use of ++ * the keyboard). ++ * ++ * The path to deliver the reset is somewhat circuitous. ++ * ++ * To deliver the reset we register an input handler, reset the keyboard and ++ * then deregister the input handler. However, to get this done right, we do ++ * have to carefully manage the calling context because we can only register ++ * input handlers from task context. ++ * ++ * In particular we need to trigger the action from the debug trap handler with ++ * all its NMI and/or NMI-like oddities. To solve this the kgdboc trap exit code ++ * (the "post_exception" callback) uses irq_work_queue(), which is NMI-safe, to ++ * schedule a callback from a hardirq context. From there we have to defer the ++ * work again, this time using schedule_work(), to get a callback using the ++ * system workqueue, which runs in task context. ++ */ + #ifdef CONFIG_KDB_KEYBOARD + static int kgdboc_reset_connect(struct input_handler *handler, + struct input_dev *dev, +@@ -99,10 +119,17 @@ static void kgdboc_restore_input_helper(struct work_struct *dummy) + + static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper); + ++static void kgdboc_queue_restore_input_helper(struct irq_work *unused) ++{ ++ schedule_work(&kgdboc_restore_input_work); ++} ++ ++static DEFINE_IRQ_WORK(kgdboc_restore_input_irq_work, kgdboc_queue_restore_input_helper); ++ + static void kgdboc_restore_input(void) + { + if (likely(system_state == SYSTEM_RUNNING)) +- schedule_work(&kgdboc_restore_input_work); ++ irq_work_queue(&kgdboc_restore_input_irq_work); + } + + static int kgdboc_register_kbd(char **cptr) +@@ -133,6 +160,7 @@ static void kgdboc_unregister_kbd(void) + i--; + } + } ++ irq_work_sync(&kgdboc_restore_input_irq_work); + flush_work(&kgdboc_restore_input_work); + } + #else /* ! CONFIG_KDB_KEYBOARD */ +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index f94f68f1e7d2b..89fc690fdf34a 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1699,7 +1699,6 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc) + */ + static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt) + { +- struct dwc3 *dwc = dep->dwc; + struct dwc3_gadget_ep_cmd_params params; + u32 cmd; + int ret; +@@ -1724,8 +1723,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int + dep->resource_index = 0; + + if (!interrupt) { +- if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A)) +- mdelay(1); ++ mdelay(1); + dep->flags &= ~DWC3_EP_TRANSFER_STARTED; + } else if (!ret) { + dep->flags |= DWC3_EP_END_TRANSFER_PENDING; +diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c +index 0717cfcd9f8ca..191f86da283d0 100644 +--- a/drivers/usb/typec/tipd/core.c ++++ b/drivers/usb/typec/tipd/core.c +@@ -28,6 +28,7 @@ + #define TPS_REG_MODE 0x03 + #define TPS_REG_CMD1 0x08 + #define TPS_REG_DATA1 0x09 ++#define TPS_REG_VERSION 0x0F + #define TPS_REG_INT_EVENT1 0x14 + #define TPS_REG_INT_EVENT2 0x15 + #define TPS_REG_INT_MASK1 0x16 +@@ -604,11 +605,11 @@ static irqreturn_t tps25750_interrupt(int irq, void *data) + if (!tps6598x_read_status(tps, &status)) + goto err_clear_ints; + +- if ((event[0] | event[1]) & TPS_REG_INT_POWER_STATUS_UPDATE) ++ if (event[0] & TPS_REG_INT_POWER_STATUS_UPDATE) + if (!tps6598x_read_power_status(tps)) + goto err_clear_ints; + +- if ((event[0] | event[1]) & TPS_REG_INT_DATA_STATUS_UPDATE) ++ if (event[0] & TPS_REG_INT_DATA_STATUS_UPDATE) + if (!tps6598x_read_data_status(tps)) + goto err_clear_ints; + +@@ -617,7 +618,7 @@ static irqreturn_t tps25750_interrupt(int irq, void *data) + * a plug event. Therefore, we need to check + * for pr/dr status change to set TypeC dr/pr accordingly. + */ +- if ((event[0] | event[1]) & TPS_REG_INT_PLUG_EVENT || ++ if (event[0] & TPS_REG_INT_PLUG_EVENT || + tps6598x_has_role_changed(tps, status)) + tps6598x_handle_plug_event(tps, status); + +@@ -636,49 +637,67 @@ static irqreturn_t tps25750_interrupt(int irq, void *data) + + static irqreturn_t tps6598x_interrupt(int irq, void *data) + { ++ int intev_len = TPS_65981_2_6_INTEVENT_LEN; + struct tps6598x *tps = data; +- u64 event1 = 0; +- u64 event2 = 0; ++ u64 event1[2] = { }; ++ u64 event2[2] = { }; ++ u32 version; + u32 status; + int ret; + + mutex_lock(&tps->lock); + +- ret = tps6598x_read64(tps, TPS_REG_INT_EVENT1, &event1); +- ret |= tps6598x_read64(tps, TPS_REG_INT_EVENT2, &event2); ++ ret = tps6598x_read32(tps, TPS_REG_VERSION, &version); ++ if (ret) ++ dev_warn(tps->dev, "%s: failed to read version (%d)\n", ++ __func__, ret); ++ ++ if (TPS_VERSION_HW_VERSION(version) == TPS_VERSION_HW_65987_8_DH || ++ TPS_VERSION_HW_VERSION(version) == TPS_VERSION_HW_65987_8_DK) ++ intev_len = TPS_65987_8_INTEVENT_LEN; ++ ++ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT1, event1, intev_len); ++ ++ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT1, event1, intev_len); + if (ret) { +- dev_err(tps->dev, "%s: failed to read events\n", __func__); ++ dev_err(tps->dev, "%s: failed to read event1\n", __func__); + goto err_unlock; + } +- trace_tps6598x_irq(event1, event2); ++ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT2, event2, intev_len); ++ if (ret) { ++ dev_err(tps->dev, "%s: failed to read event2\n", __func__); ++ goto err_unlock; ++ } ++ trace_tps6598x_irq(event1[0], event2[0]); + +- if (!(event1 | event2)) ++ if (!(event1[0] | event1[1] | event2[0] | event2[1])) + goto err_unlock; + + if (!tps6598x_read_status(tps, &status)) + goto err_clear_ints; + +- if ((event1 | event2) & TPS_REG_INT_POWER_STATUS_UPDATE) ++ if ((event1[0] | event2[0]) & TPS_REG_INT_POWER_STATUS_UPDATE) + if (!tps6598x_read_power_status(tps)) + goto err_clear_ints; + +- if ((event1 | event2) & TPS_REG_INT_DATA_STATUS_UPDATE) ++ if ((event1[0] | event2[0]) & TPS_REG_INT_DATA_STATUS_UPDATE) + if (!tps6598x_read_data_status(tps)) + goto err_clear_ints; + + /* Handle plug insert or removal */ +- if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) ++ if ((event1[0] | event2[0]) & TPS_REG_INT_PLUG_EVENT) + tps6598x_handle_plug_event(tps, status); + + err_clear_ints: +- tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event1); +- tps6598x_write64(tps, TPS_REG_INT_CLEAR2, event2); ++ tps6598x_block_write(tps, TPS_REG_INT_CLEAR1, event1, intev_len); ++ tps6598x_block_write(tps, TPS_REG_INT_CLEAR2, event2, intev_len); + + err_unlock: + mutex_unlock(&tps->lock); + +- if (event1 | event2) ++ if (event1[0] | event1[1] | event2[0] | event2[1]) + return IRQ_HANDLED; ++ + return IRQ_NONE; + } + +diff --git a/drivers/usb/typec/tipd/tps6598x.h b/drivers/usb/typec/tipd/tps6598x.h +index 89b24519463a1..9b23e90174521 100644 +--- a/drivers/usb/typec/tipd/tps6598x.h ++++ b/drivers/usb/typec/tipd/tps6598x.h +@@ -253,4 +253,15 @@ + #define TPS_PTCC_DEV 2 + #define TPS_PTCC_APP 3 + ++/* Version Register */ ++#define TPS_VERSION_HW_VERSION_MASK GENMASK(31, 24) ++#define TPS_VERSION_HW_VERSION(x) TPS_FIELD_GET(TPS_VERSION_HW_VERSION_MASK, (x)) ++#define TPS_VERSION_HW_65981_2_6 0x00 ++#define TPS_VERSION_HW_65987_8_DH 0xF7 ++#define TPS_VERSION_HW_65987_8_DK 0xF9 ++ ++/* Int Event Register length */ ++#define TPS_65981_2_6_INTEVENT_LEN 8 ++#define TPS_65987_8_INTEVENT_LEN 11 ++ + #endif /* __TPS6598X_H__ */ +diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c +index d9d3c91125ca8..8be92fc1d12c9 100644 +--- a/drivers/usb/typec/ucsi/displayport.c ++++ b/drivers/usb/typec/ucsi/displayport.c +@@ -275,8 +275,6 @@ static void ucsi_displayport_work(struct work_struct *work) + struct ucsi_dp *dp = container_of(work, struct ucsi_dp, work); + int ret; + +- mutex_lock(&dp->con->lock); +- + ret = typec_altmode_vdm(dp->alt, dp->header, + dp->vdo_data, dp->vdo_size); + if (ret) +@@ -285,8 +283,6 @@ static void ucsi_displayport_work(struct work_struct *work) + dp->vdo_data = NULL; + dp->vdo_size = 0; + dp->header = 0; +- +- mutex_unlock(&dp->con->lock); + } + + void ucsi_displayport_remove_partner(struct typec_altmode *alt) +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 69e7da33ca49a..00e62b81a7363 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -233,6 +233,19 @@ static inline unsigned int disk_openers(struct gendisk *disk) + return atomic_read(&disk->part0->bd_openers); + } + ++/** ++ * disk_has_partscan - return %true if partition scanning is enabled on a disk ++ * @disk: disk to check ++ * ++ * Returns %true if partitions scanning is enabled for @disk, or %false if ++ * partition scanning is disabled either permanently or temporarily. ++ */ ++static inline bool disk_has_partscan(struct gendisk *disk) ++{ ++ return !(disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN)) && ++ !test_bit(GD_SUPPRESS_PART_SCAN, &disk->state); ++} ++ + /* + * The gendisk is refcounted by the part0 block_device, and the bd_device + * therein is also used for device model presentation in sysfs. +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index 5c12761cbc0e2..07198beb3d80b 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -1666,6 +1666,15 @@ struct hci_cp_le_set_event_mask { + __u8 mask[8]; + } __packed; + ++/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E ++ * 7.8.2 LE Read Buffer Size command ++ * MAX_LE_MTU is 0xffff. ++ * 0 is also valid. It means that no dedicated LE Buffer exists. ++ * It should use the HCI_Read_Buffer_Size command and mtu is shared ++ * between BR/EDR and LE. ++ */ ++#define HCI_MIN_LE_MTU 0x001b ++ + #define HCI_OP_LE_READ_BUFFER_SIZE 0x2002 + struct hci_rp_le_read_buffer_size { + __u8 status; +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index e8f581f3f3ce6..b1c8489ff93e4 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -706,6 +706,7 @@ struct hci_conn { + __u16 handle; + __u16 sync_handle; + __u16 state; ++ __u16 mtu; + __u8 mode; + __u8 type; + __u8 role; +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 05346250f7195..6ab404dda7949 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -909,11 +909,37 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, + { + struct hci_conn *conn; + ++ switch (type) { ++ case ACL_LINK: ++ if (!hdev->acl_mtu) ++ return ERR_PTR(-ECONNREFUSED); ++ break; ++ case ISO_LINK: ++ if (hdev->iso_mtu) ++ /* Dedicated ISO Buffer exists */ ++ break; ++ fallthrough; ++ case LE_LINK: ++ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU) ++ return ERR_PTR(-ECONNREFUSED); ++ if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU) ++ return ERR_PTR(-ECONNREFUSED); ++ break; ++ case SCO_LINK: ++ case ESCO_LINK: ++ if (!hdev->sco_pkts) ++ /* Controller does not support SCO or eSCO over HCI */ ++ return ERR_PTR(-ECONNREFUSED); ++ break; ++ default: ++ return ERR_PTR(-ECONNREFUSED); ++ } ++ + bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle); + + conn = kzalloc(sizeof(*conn), GFP_KERNEL); + if (!conn) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + bacpy(&conn->dst, dst); + bacpy(&conn->src, &hdev->bdaddr); +@@ -944,10 +970,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, + switch (type) { + case ACL_LINK: + conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; ++ conn->mtu = hdev->acl_mtu; + break; + case LE_LINK: + /* conn->src should reflect the local identity address */ + hci_copy_identity_address(hdev, &conn->src, &conn->src_type); ++ conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu; + break; + case ISO_LINK: + /* conn->src should reflect the local identity address */ +@@ -959,6 +987,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, + else if (conn->role == HCI_ROLE_MASTER) + conn->cleanup = cis_cleanup; + ++ conn->mtu = hdev->iso_mtu ? hdev->iso_mtu : ++ hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu; + break; + case SCO_LINK: + if (lmp_esco_capable(hdev)) +@@ -966,9 +996,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, + (hdev->esco_type & EDR_ESCO_MASK); + else + conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; ++ ++ conn->mtu = hdev->sco_mtu; + break; + case ESCO_LINK: + conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK; ++ conn->mtu = hdev->sco_mtu; + break; + } + +@@ -1011,7 +1044,7 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type, + + handle = hci_conn_hash_alloc_unset(hdev); + if (unlikely(handle < 0)) +- return NULL; ++ return ERR_PTR(-ECONNREFUSED); + + return hci_conn_add(hdev, type, dst, role, handle); + } +@@ -1317,8 +1350,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, + bacpy(&conn->dst, dst); + } else { + conn = hci_conn_add_unset(hdev, LE_LINK, dst, role); +- if (!conn) +- return ERR_PTR(-ENOMEM); ++ if (IS_ERR(conn)) ++ return conn; + hci_conn_hold(conn); + conn->pending_sec_level = sec_level; + } +@@ -1494,8 +1527,8 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst, + return ERR_PTR(-EADDRINUSE); + + conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER); +- if (!conn) +- return ERR_PTR(-ENOMEM); ++ if (IS_ERR(conn)) ++ return conn; + + conn->state = BT_CONNECT; + +@@ -1538,8 +1571,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, + BT_DBG("requesting refresh of dst_addr"); + + conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER); +- if (!conn) +- return ERR_PTR(-ENOMEM); ++ if (IS_ERR(conn)) ++ return conn; + + if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) { + hci_conn_del(conn); +@@ -1586,8 +1619,8 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, + acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); + if (!acl) { + acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER); +- if (!acl) +- return ERR_PTR(-ENOMEM); ++ if (IS_ERR(acl)) ++ return acl; + } + + hci_conn_hold(acl); +@@ -1655,9 +1688,9 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, + sco = hci_conn_hash_lookup_ba(hdev, type, dst); + if (!sco) { + sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER); +- if (!sco) { ++ if (IS_ERR(sco)) { + hci_conn_drop(acl); +- return ERR_PTR(-ENOMEM); ++ return sco; + } + } + +@@ -1847,8 +1880,8 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, + qos->ucast.cis); + if (!cis) { + cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER); +- if (!cis) +- return ERR_PTR(-ENOMEM); ++ if (IS_ERR(cis)) ++ return cis; + cis->cleanup = cis_cleanup; + cis->dst_type = dst_type; + cis->iso_qos.ucast.cig = BT_ISO_QOS_CIG_UNSET; +@@ -1983,14 +2016,8 @@ static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn, + struct bt_iso_io_qos *qos, __u8 phy) + { + /* Only set MTU if PHY is enabled */ +- if (!qos->sdu && qos->phy) { +- if (hdev->iso_mtu > 0) +- qos->sdu = hdev->iso_mtu; +- else if (hdev->le_mtu > 0) +- qos->sdu = hdev->le_mtu; +- else +- qos->sdu = hdev->acl_mtu; +- } ++ if (!qos->sdu && qos->phy) ++ qos->sdu = conn->mtu; + + /* Use the same PHY as ACL if set to any */ + if (qos->phy == BT_ISO_PHY_ANY) +@@ -2071,8 +2098,8 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, + return ERR_PTR(-EBUSY); + + conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE); +- if (!conn) +- return ERR_PTR(-ENOMEM); ++ if (IS_ERR(conn)) ++ return conn; + + conn->iso_qos = *qos; + conn->state = BT_LISTEN; +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index d72d238c1656e..4de8f0dc1a523 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -954,6 +954,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data, + BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, + hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); + ++ if (!hdev->acl_mtu || !hdev->acl_pkts) ++ return HCI_ERROR_INVALID_PARAMETERS; ++ + return rp->status; + } + +@@ -1263,6 +1266,9 @@ static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data, + + BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); + ++ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU) ++ return HCI_ERROR_INVALID_PARAMETERS; ++ + return rp->status; + } + +@@ -2342,8 +2348,8 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) + if (!conn) { + conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr, + HCI_ROLE_MASTER); +- if (!conn) +- bt_dev_err(hdev, "no memory for new connection"); ++ if (IS_ERR(conn)) ++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); + } + } + +@@ -3154,8 +3160,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, + BDADDR_BREDR)) { + conn = hci_conn_add_unset(hdev, ev->link_type, + &ev->bdaddr, HCI_ROLE_SLAVE); +- if (!conn) { +- bt_dev_err(hdev, "no memory for new conn"); ++ if (IS_ERR(conn)) { ++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); + goto unlock; + } + } else { +@@ -3343,8 +3349,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data, + if (!conn) { + conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr, + HCI_ROLE_SLAVE); +- if (!conn) { +- bt_dev_err(hdev, "no memory for new connection"); ++ if (IS_ERR(conn)) { ++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); + goto unlock; + } + } +@@ -3821,6 +3827,9 @@ static u8 hci_cc_le_read_buffer_size_v2(struct hci_dev *hdev, void *data, + BT_DBG("%s acl mtu %d:%d iso mtu %d:%d", hdev->name, hdev->acl_mtu, + hdev->acl_pkts, hdev->iso_mtu, hdev->iso_pkts); + ++ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU) ++ return HCI_ERROR_INVALID_PARAMETERS; ++ + return rp->status; + } + +@@ -5768,8 +5777,8 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, + goto unlock; + + conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role); +- if (!conn) { +- bt_dev_err(hdev, "no memory for new connection"); ++ if (IS_ERR(conn)) { ++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); + goto unlock; + } + +@@ -6898,7 +6907,7 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data, + if (!cis) { + cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE, + cis_handle); +- if (!cis) { ++ if (IS_ERR(cis)) { + hci_le_reject_cis(hdev, ev->cis_handle); + goto unlock; + } +@@ -7007,7 +7016,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, + if (!bis) { + bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY, + HCI_ROLE_SLAVE, handle); +- if (!bis) ++ if (IS_ERR(bis)) + continue; + } + +@@ -7079,7 +7088,7 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data, + pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY, + HCI_ROLE_SLAVE); + +- if (!pa_sync) ++ if (IS_ERR(pa_sync)) + goto unlock; + + pa_sync->sync_handle = le16_to_cpu(ev->sync_handle); +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index ef0cc80b4c0cc..6bed4aa8291de 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -1285,7 +1285,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg, + return -ENOTCONN; + } + +- mtu = iso_pi(sk)->conn->hcon->hdev->iso_mtu; ++ mtu = iso_pi(sk)->conn->hcon->mtu; + + release_sock(sk); + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 9223b1a698e3a..3f7a82f10fe98 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6241,7 +6241,7 @@ static int l2cap_finish_move(struct l2cap_chan *chan) + BT_DBG("chan %p", chan); + + chan->rx_state = L2CAP_RX_STATE_RECV; +- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; ++ chan->conn->mtu = chan->conn->hcon->mtu; + + return l2cap_resegment(chan); + } +@@ -6308,7 +6308,7 @@ static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, + */ + chan->next_tx_seq = control->reqseq; + chan->unacked_frames = 0; +- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; ++ chan->conn->mtu = chan->conn->hcon->mtu; + + err = l2cap_resegment(chan); + +@@ -6848,18 +6848,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) + + BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); + +- switch (hcon->type) { +- case LE_LINK: +- if (hcon->hdev->le_mtu) { +- conn->mtu = hcon->hdev->le_mtu; +- break; +- } +- fallthrough; +- default: +- conn->mtu = hcon->hdev->acl_mtu; +- break; +- } +- ++ conn->mtu = hcon->mtu; + conn->feat_mask = 0; + + conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index e0ad30862ee41..71d36582d4efa 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -126,7 +126,6 @@ static void sco_sock_clear_timer(struct sock *sk) + /* ---- SCO connections ---- */ + static struct sco_conn *sco_conn_add(struct hci_conn *hcon) + { +- struct hci_dev *hdev = hcon->hdev; + struct sco_conn *conn = hcon->sco_data; + + if (conn) { +@@ -144,9 +143,10 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) + + hcon->sco_data = conn; + conn->hcon = hcon; ++ conn->mtu = hcon->mtu; + +- if (hdev->sco_mtu > 0) +- conn->mtu = hdev->sco_mtu; ++ if (hcon->mtu > 0) ++ conn->mtu = hcon->mtu; + else + conn->mtu = 60; + +diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c +index bc700f85f80be..ea277c55a38db 100644 +--- a/security/keys/trusted-keys/trusted_tpm2.c ++++ b/security/keys/trusted-keys/trusted_tpm2.c +@@ -38,6 +38,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, + u8 *end_work = scratch + SCRATCH_SIZE; + u8 *priv, *pub; + u16 priv_len, pub_len; ++ int ret; + + priv_len = get_unaligned_be16(src) + 2; + priv = src; +@@ -57,8 +58,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, + unsigned char bool[3], *w = bool; + /* tag 0 is emptyAuth */ + w = asn1_encode_boolean(w, w + sizeof(bool), true); +- if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) +- return PTR_ERR(w); ++ if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) { ++ ret = PTR_ERR(w); ++ goto err; ++ } + work = asn1_encode_tag(work, end_work, 0, bool, w - bool); + } + +@@ -69,8 +72,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, + * trigger, so if it does there's something nefarious going on + */ + if (WARN(work - scratch + pub_len + priv_len + 14 > SCRATCH_SIZE, +- "BUG: scratch buffer is too small")) +- return -EINVAL; ++ "BUG: scratch buffer is too small")) { ++ ret = -EINVAL; ++ goto err; ++ } + + work = asn1_encode_integer(work, end_work, options->keyhandle); + work = asn1_encode_octet_string(work, end_work, pub, pub_len); +@@ -79,10 +84,18 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, + work1 = payload->blob; + work1 = asn1_encode_sequence(work1, work1 + sizeof(payload->blob), + scratch, work - scratch); +- if (WARN(IS_ERR(work1), "BUG: ASN.1 encoder failed")) +- return PTR_ERR(work1); ++ if (IS_ERR(work1)) { ++ ret = PTR_ERR(work1); ++ pr_err("BUG: ASN.1 encoder failed with %d\n", ret); ++ goto err; ++ } + ++ kfree(scratch); + return work1 - payload->blob; ++ ++err: ++ kfree(scratch); ++ return ret; + } + + struct tpm2_key_context { +diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile +index bbf796a5f7ba8..08cfd4baecdd7 100644 +--- a/sound/soc/intel/boards/Makefile ++++ b/sound/soc/intel/boards/Makefile +@@ -42,6 +42,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o \ + sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ + sof_sdw_rt712_sdca.o sof_sdw_rt715.o \ + sof_sdw_rt715_sdca.o sof_sdw_rt722_sdca.o \ ++ sof_sdw_rt_dmic.o \ + sof_sdw_cs42l42.o sof_sdw_cs42l43.o \ + sof_sdw_cs_amp.o \ + sof_sdw_dmic.o \ +diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c +index 08f330ed5c2ea..a90b43162a54b 100644 +--- a/sound/soc/intel/boards/sof_sdw.c ++++ b/sound/soc/intel/boards/sof_sdw.c +@@ -730,7 +730,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { + .dai_name = "rt712-sdca-dmic-aif1", + .dai_type = SOF_SDW_DAI_TYPE_MIC, + .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, +- .rtd_init = rt712_sdca_dmic_rtd_init, ++ .rtd_init = rt_dmic_rtd_init, + }, + }, + .dai_num = 1, +@@ -760,7 +760,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { + .dai_name = "rt712-sdca-dmic-aif1", + .dai_type = SOF_SDW_DAI_TYPE_MIC, + .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, +- .rtd_init = rt712_sdca_dmic_rtd_init, ++ .rtd_init = rt_dmic_rtd_init, + }, + }, + .dai_num = 1, +@@ -822,7 +822,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { + .dai_name = "rt715-aif2", + .dai_type = SOF_SDW_DAI_TYPE_MIC, + .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, +- .rtd_init = rt715_sdca_rtd_init, ++ .rtd_init = rt_dmic_rtd_init, + }, + }, + .dai_num = 1, +@@ -837,7 +837,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { + .dai_name = "rt715-aif2", + .dai_type = SOF_SDW_DAI_TYPE_MIC, + .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, +- .rtd_init = rt715_sdca_rtd_init, ++ .rtd_init = rt_dmic_rtd_init, + }, + }, + .dai_num = 1, +@@ -852,7 +852,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { + .dai_name = "rt715-aif2", + .dai_type = SOF_SDW_DAI_TYPE_MIC, + .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, +- .rtd_init = rt715_rtd_init, ++ .rtd_init = rt_dmic_rtd_init, + }, + }, + .dai_num = 1, +@@ -867,7 +867,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { + .dai_name = "rt715-aif2", + .dai_type = SOF_SDW_DAI_TYPE_MIC, + .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, +- .rtd_init = rt715_rtd_init, ++ .rtd_init = rt_dmic_rtd_init, + }, + }, + .dai_num = 1, +diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h +index b1d57034361c4..8a541b6bb0ac3 100644 +--- a/sound/soc/intel/boards/sof_sdw_common.h ++++ b/sound/soc/intel/boards/sof_sdw_common.h +@@ -190,6 +190,7 @@ int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); + int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); + int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd); + int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd); ++int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); + int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); + int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); + +diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c +new file mode 100644 +index 0000000000000..9091f5b5c6484 +--- /dev/null ++++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c +@@ -0,0 +1,52 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// Copyright (c) 2024 Intel Corporation ++ ++/* ++ * sof_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver ++ */ ++ ++#include <linux/device.h> ++#include <linux/errno.h> ++#include <sound/soc.h> ++#include <sound/soc-acpi.h> ++#include "sof_board_helpers.h" ++#include "sof_sdw_common.h" ++ ++static const char * const dmics[] = { ++ "rt715", ++ "rt712-sdca-dmic", ++}; ++ ++int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_component *component; ++ struct snd_soc_dai *codec_dai; ++ char *mic_name; ++ ++ codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); ++ if (!codec_dai) ++ return -EINVAL; ++ ++ component = codec_dai->component; ++ ++ /* ++ * rt715-sdca (aka rt714) is a special case that uses different name in card->components ++ * and component->name_prefix. ++ */ ++ if (!strcmp(component->name_prefix, "rt714")) ++ mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "rt715-sdca"); ++ else ++ mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s", component->name_prefix); ++ ++ card->components = devm_kasprintf(card->dev, GFP_KERNEL, ++ "%s mic:%s", card->components, ++ mic_name); ++ if (!card->components) ++ return -ENOMEM; ++ ++ dev_dbg(card->dev, "card->components: %s\n", card->components); ++ ++ return 0; ++} ++MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); diff --git a/1002_linux-6.9.3.patch b/1002_linux-6.9.3.patch new file mode 100644 index 00000000..e699e5e2 --- /dev/null +++ b/1002_linux-6.9.3.patch @@ -0,0 +1,18354 @@ +diff --git a/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml b/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml +index 3d49d21ad33df..e1f450b80db27 100644 +--- a/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml ++++ b/Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml +@@ -28,6 +28,9 @@ properties: + reg: + maxItems: 1 + ++ clocks: ++ maxItems: 1 ++ + dmas: + maxItems: 1 + +@@ -48,6 +51,7 @@ required: + - compatible + - dmas + - reg ++ - clocks + + additionalProperties: false + +@@ -58,6 +62,7 @@ examples: + reg = <0x44a00000 0x10000>; + dmas = <&rx_dma 0>; + dma-names = "rx"; ++ clocks = <&axi_clk>; + #io-backend-cells = <0>; + }; + ... +diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml +index cf456f8d9ddcb..c87677f5e2a25 100644 +--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml ++++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml +@@ -37,15 +37,15 @@ properties: + active low. + maxItems: 1 + +- dovdd-supply: ++ DOVDD-supply: + description: + Definition of the regulator used as interface power supply. + +- avdd-supply: ++ AVDD-supply: + description: + Definition of the regulator used as analog power supply. + +- dvdd-supply: ++ DVDD-supply: + description: + Definition of the regulator used as digital power supply. + +@@ -59,9 +59,9 @@ required: + - reg + - clocks + - clock-names +- - dovdd-supply +- - avdd-supply +- - dvdd-supply ++ - DOVDD-supply ++ - AVDD-supply ++ - DVDD-supply + - reset-gpios + - port + +@@ -82,9 +82,9 @@ examples: + clock-names = "xvclk"; + reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + +- dovdd-supply = <&sw2_reg>; +- dvdd-supply = <&sw2_reg>; +- avdd-supply = <®_peri_3p15v>; ++ DOVDD-supply = <&sw2_reg>; ++ DVDD-supply = <&sw2_reg>; ++ AVDD-supply = <®_peri_3p15v>; + + port { + ov2680_to_mipi: endpoint { +diff --git a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml +index b634f57cd011d..ca81c8afba79c 100644 +--- a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml ++++ b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml +@@ -18,13 +18,15 @@ properties: + oneOf: + - enum: + - loongson,ls2k1000-thermal ++ - loongson,ls2k2000-thermal + - items: + - enum: +- - loongson,ls2k2000-thermal ++ - loongson,ls2k0500-thermal + - const: loongson,ls2k1000-thermal + + reg: +- maxItems: 1 ++ minItems: 1 ++ maxItems: 2 + + interrupts: + maxItems: 1 +@@ -38,6 +40,24 @@ required: + - interrupts + - '#thermal-sensor-cells' + ++if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - loongson,ls2k2000-thermal ++ ++then: ++ properties: ++ reg: ++ minItems: 2 ++ maxItems: 2 ++ ++else: ++ properties: ++ reg: ++ maxItems: 1 ++ + unevaluatedProperties: false + + examples: +diff --git a/Makefile b/Makefile +index 8302496ee7a57..8def0819eb55b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 9 +-SUBLEVEL = 2 ++SUBLEVEL = 3 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig +index bddc82f789421..a83d29fed1756 100644 +--- a/arch/arm/configs/sunxi_defconfig ++++ b/arch/arm/configs/sunxi_defconfig +@@ -110,6 +110,7 @@ CONFIG_DRM_PANEL_LVDS=y + CONFIG_DRM_PANEL_SIMPLE=y + CONFIG_DRM_PANEL_EDP=y + CONFIG_DRM_SIMPLE_BRIDGE=y ++CONFIG_DRM_DW_HDMI=y + CONFIG_DRM_LIMA=y + CONFIG_FB_SIMPLE=y + CONFIG_BACKLIGHT_CLASS_DEVICE=y +diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h +index 0a7186a93882d..d4d7451c2c129 100644 +--- a/arch/arm64/include/asm/irqflags.h ++++ b/arch/arm64/include/asm/irqflags.h +@@ -5,7 +5,6 @@ + #ifndef __ASM_IRQFLAGS_H + #define __ASM_IRQFLAGS_H + +-#include <asm/alternative.h> + #include <asm/barrier.h> + #include <asm/ptrace.h> + #include <asm/sysreg.h> +diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c +index ebb0158997cab..82e8a60173828 100644 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -1535,6 +1535,27 @@ static void fpsimd_save_kernel_state(struct task_struct *task) + task->thread.kernel_fpsimd_cpu = smp_processor_id(); + } + ++/* ++ * Invalidate any task's FPSIMD state that is present on this cpu. ++ * The FPSIMD context should be acquired with get_cpu_fpsimd_context() ++ * before calling this function. ++ */ ++static void fpsimd_flush_cpu_state(void) ++{ ++ WARN_ON(!system_supports_fpsimd()); ++ __this_cpu_write(fpsimd_last_state.st, NULL); ++ ++ /* ++ * Leaving streaming mode enabled will cause issues for any kernel ++ * NEON and leaving streaming mode or ZA enabled may increase power ++ * consumption. ++ */ ++ if (system_supports_sme()) ++ sme_smstop(); ++ ++ set_thread_flag(TIF_FOREIGN_FPSTATE); ++} ++ + void fpsimd_thread_switch(struct task_struct *next) + { + bool wrong_task, wrong_cpu; +@@ -1552,7 +1573,7 @@ void fpsimd_thread_switch(struct task_struct *next) + + if (test_tsk_thread_flag(next, TIF_KERNEL_FPSTATE)) { + fpsimd_load_kernel_state(next); +- set_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE); ++ fpsimd_flush_cpu_state(); + } else { + /* + * Fix up TIF_FOREIGN_FPSTATE to correctly describe next's +@@ -1842,27 +1863,6 @@ void fpsimd_flush_task_state(struct task_struct *t) + barrier(); + } + +-/* +- * Invalidate any task's FPSIMD state that is present on this cpu. +- * The FPSIMD context should be acquired with get_cpu_fpsimd_context() +- * before calling this function. +- */ +-static void fpsimd_flush_cpu_state(void) +-{ +- WARN_ON(!system_supports_fpsimd()); +- __this_cpu_write(fpsimd_last_state.st, NULL); +- +- /* +- * Leaving streaming mode enabled will cause issues for any kernel +- * NEON and leaving streaming mode or ZA enabled may increase power +- * consumption. +- */ +- if (system_supports_sme()) +- sme_smstop(); +- +- set_thread_flag(TIF_FOREIGN_FPSTATE); +-} +- + /* + * Save the FPSIMD state to memory and invalidate cpu view. + * This function must be called with preemption disabled. +diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig +index 6ffa295851945..99837d4e8c977 100644 +--- a/arch/m68k/Kconfig ++++ b/arch/m68k/Kconfig +@@ -3,8 +3,8 @@ config M68K + bool + default y + select ARCH_32BIT_OFF_T +- select ARCH_HAS_CPU_CACHE_ALIASING + select ARCH_HAS_BINFMT_FLAT ++ select ARCH_HAS_CPU_CACHE_ALIASING + select ARCH_HAS_CPU_FINALIZE_INIT if MMU + select ARCH_HAS_CURRENT_STACK_POINTER + select ARCH_HAS_DMA_PREP_COHERENT if M68K_NONCOHERENT_DMA && !COLDFIRE +diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S +index 3bcdd32a6b366..338b474910f74 100644 +--- a/arch/m68k/kernel/entry.S ++++ b/arch/m68k/kernel/entry.S +@@ -430,7 +430,9 @@ resume: + movec %a0,%dfc + + /* restore status register */ +- movew %a1@(TASK_THREAD+THREAD_SR),%sr ++ movew %a1@(TASK_THREAD+THREAD_SR),%d0 ++ oriw #0x0700,%d0 ++ movew %d0,%sr + + rts + +diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c +index 4c8f8cbfa05f3..e7f0f72c1b36e 100644 +--- a/arch/m68k/mac/misc.c ++++ b/arch/m68k/mac/misc.c +@@ -453,30 +453,18 @@ void mac_poweroff(void) + + void mac_reset(void) + { +- if (macintosh_config->adb_type == MAC_ADB_II && +- macintosh_config->ident != MAC_MODEL_SE30) { +- /* need ROMBASE in booter */ +- /* indeed, plus need to MAP THE ROM !! */ +- +- if (mac_bi_data.rombase == 0) +- mac_bi_data.rombase = 0x40800000; +- +- /* works on some */ +- rom_reset = (void *) (mac_bi_data.rombase + 0xa); +- +- local_irq_disable(); +- rom_reset(); + #ifdef CONFIG_ADB_CUDA +- } else if (macintosh_config->adb_type == MAC_ADB_EGRET || +- macintosh_config->adb_type == MAC_ADB_CUDA) { ++ if (macintosh_config->adb_type == MAC_ADB_EGRET || ++ macintosh_config->adb_type == MAC_ADB_CUDA) { + cuda_restart(); ++ } else + #endif + #ifdef CONFIG_ADB_PMU +- } else if (macintosh_config->adb_type == MAC_ADB_PB2) { ++ if (macintosh_config->adb_type == MAC_ADB_PB2) { + pmu_restart(); ++ } else + #endif +- } else if (CPU_IS_030) { +- ++ if (CPU_IS_030) { + /* 030-specific reset routine. The idea is general, but the + * specific registers to reset are '030-specific. Until I + * have a non-030 machine, I can't test anything else. +@@ -524,6 +512,18 @@ void mac_reset(void) + "jmp %/a0@\n\t" /* jump to the reset vector */ + ".chip 68k" + : : "r" (offset), "a" (rombase) : "a0"); ++ } else { ++ /* need ROMBASE in booter */ ++ /* indeed, plus need to MAP THE ROM !! */ ++ ++ if (mac_bi_data.rombase == 0) ++ mac_bi_data.rombase = 0x40800000; ++ ++ /* works on some */ ++ rom_reset = (void *)(mac_bi_data.rombase + 0xa); ++ ++ local_irq_disable(); ++ rom_reset(); + } + + /* should never get here */ +diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c +index 86e02929f3ace..3c27d1c727189 100644 +--- a/arch/openrisc/kernel/process.c ++++ b/arch/openrisc/kernel/process.c +@@ -65,7 +65,7 @@ void machine_restart(char *cmd) + } + + /* +- * This is used if pm_power_off has not been set by a power management ++ * This is used if a sys-off handler was not set by a power management + * driver, in this case we can assume we are on a simulator. On + * OpenRISC simulators l.nop 1 will trigger the simulator exit. + */ +@@ -89,10 +89,8 @@ void machine_halt(void) + void machine_power_off(void) + { + printk(KERN_INFO "*** MACHINE POWER OFF ***\n"); +- if (pm_power_off != NULL) +- pm_power_off(); +- else +- default_power_off(); ++ do_kernel_power_off(); ++ default_power_off(); + } + + /* +diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c +index 9370888c9a7e3..90554a5558fbc 100644 +--- a/arch/openrisc/kernel/traps.c ++++ b/arch/openrisc/kernel/traps.c +@@ -180,29 +180,39 @@ asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector) + + asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address) + { +- int code = FPE_FLTUNK; +- unsigned long fpcsr = regs->fpcsr; +- +- if (fpcsr & SPR_FPCSR_IVF) +- code = FPE_FLTINV; +- else if (fpcsr & SPR_FPCSR_OVF) +- code = FPE_FLTOVF; +- else if (fpcsr & SPR_FPCSR_UNF) +- code = FPE_FLTUND; +- else if (fpcsr & SPR_FPCSR_DZF) +- code = FPE_FLTDIV; +- else if (fpcsr & SPR_FPCSR_IXF) +- code = FPE_FLTRES; +- +- /* Clear all flags */ +- regs->fpcsr &= ~SPR_FPCSR_ALLF; +- +- force_sig_fault(SIGFPE, code, (void __user *)regs->pc); ++ if (user_mode(regs)) { ++ int code = FPE_FLTUNK; ++ unsigned long fpcsr = regs->fpcsr; ++ ++ if (fpcsr & SPR_FPCSR_IVF) ++ code = FPE_FLTINV; ++ else if (fpcsr & SPR_FPCSR_OVF) ++ code = FPE_FLTOVF; ++ else if (fpcsr & SPR_FPCSR_UNF) ++ code = FPE_FLTUND; ++ else if (fpcsr & SPR_FPCSR_DZF) ++ code = FPE_FLTDIV; ++ else if (fpcsr & SPR_FPCSR_IXF) ++ code = FPE_FLTRES; ++ ++ /* Clear all flags */ ++ regs->fpcsr &= ~SPR_FPCSR_ALLF; ++ ++ force_sig_fault(SIGFPE, code, (void __user *)regs->pc); ++ } else { ++ pr_emerg("KERNEL: Illegal fpe exception 0x%.8lx\n", regs->pc); ++ die("Die:", regs, SIGFPE); ++ } + } + + asmlinkage void do_trap(struct pt_regs *regs, unsigned long address) + { +- force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc); ++ if (user_mode(regs)) { ++ force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc); ++ } else { ++ pr_emerg("KERNEL: Illegal trap exception 0x%.8lx\n", regs->pc); ++ die("Die:", regs, SIGILL); ++ } + } + + asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address) +diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c +index 6f0c92e8149d8..dcf61cbd31470 100644 +--- a/arch/parisc/kernel/parisc_ksyms.c ++++ b/arch/parisc/kernel/parisc_ksyms.c +@@ -22,6 +22,7 @@ EXPORT_SYMBOL(memset); + #include <linux/atomic.h> + EXPORT_SYMBOL(__xchg8); + EXPORT_SYMBOL(__xchg32); ++EXPORT_SYMBOL(__cmpxchg_u8); + EXPORT_SYMBOL(__cmpxchg_u32); + EXPORT_SYMBOL(__cmpxchg_u64); + #ifdef CONFIG_SMP +diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c +index 8e6c84df4ca10..e205135ae1fea 100644 +--- a/arch/powerpc/sysdev/fsl_msi.c ++++ b/arch/powerpc/sysdev/fsl_msi.c +@@ -564,10 +564,12 @@ static const struct fsl_msi_feature ipic_msi_feature = { + .msiir_offset = 0x38, + }; + ++#ifdef CONFIG_EPAPR_PARAVIRT + static const struct fsl_msi_feature vmpic_msi_feature = { + .fsl_pic_ip = FSL_PIC_IP_VMPIC, + .msiir_offset = 0, + }; ++#endif + + static const struct of_device_id fsl_of_msi_ids[] = { + { +diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h +index 2468c55933cd0..9d1b07932794e 100644 +--- a/arch/riscv/include/asm/csr.h ++++ b/arch/riscv/include/asm/csr.h +@@ -281,7 +281,7 @@ + #define CSR_HPMCOUNTER30H 0xc9e + #define CSR_HPMCOUNTER31H 0xc9f + +-#define CSR_SSCOUNTOVF 0xda0 ++#define CSR_SCOUNTOVF 0xda0 + + #define CSR_SSTATUS 0x100 + #define CSR_SIE 0x104 +diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c +index ec9d692838fca..fb5d1950042b7 100644 +--- a/arch/riscv/net/bpf_jit_comp64.c ++++ b/arch/riscv/net/bpf_jit_comp64.c +@@ -498,33 +498,33 @@ static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64, + break; + /* src_reg = atomic_fetch_<op>(dst_reg + off16, src_reg) */ + case BPF_ADD | BPF_FETCH: +- emit(is64 ? rv_amoadd_d(rs, rs, rd, 0, 0) : +- rv_amoadd_w(rs, rs, rd, 0, 0), ctx); ++ emit(is64 ? rv_amoadd_d(rs, rs, rd, 1, 1) : ++ rv_amoadd_w(rs, rs, rd, 1, 1), ctx); + if (!is64) + emit_zextw(rs, rs, ctx); + break; + case BPF_AND | BPF_FETCH: +- emit(is64 ? rv_amoand_d(rs, rs, rd, 0, 0) : +- rv_amoand_w(rs, rs, rd, 0, 0), ctx); ++ emit(is64 ? rv_amoand_d(rs, rs, rd, 1, 1) : ++ rv_amoand_w(rs, rs, rd, 1, 1), ctx); + if (!is64) + emit_zextw(rs, rs, ctx); + break; + case BPF_OR | BPF_FETCH: +- emit(is64 ? rv_amoor_d(rs, rs, rd, 0, 0) : +- rv_amoor_w(rs, rs, rd, 0, 0), ctx); ++ emit(is64 ? rv_amoor_d(rs, rs, rd, 1, 1) : ++ rv_amoor_w(rs, rs, rd, 1, 1), ctx); + if (!is64) + emit_zextw(rs, rs, ctx); + break; + case BPF_XOR | BPF_FETCH: +- emit(is64 ? rv_amoxor_d(rs, rs, rd, 0, 0) : +- rv_amoxor_w(rs, rs, rd, 0, 0), ctx); ++ emit(is64 ? rv_amoxor_d(rs, rs, rd, 1, 1) : ++ rv_amoxor_w(rs, rs, rd, 1, 1), ctx); + if (!is64) + emit_zextw(rs, rs, ctx); + break; + /* src_reg = atomic_xchg(dst_reg + off16, src_reg); */ + case BPF_XCHG: +- emit(is64 ? rv_amoswap_d(rs, rs, rd, 0, 0) : +- rv_amoswap_w(rs, rs, rd, 0, 0), ctx); ++ emit(is64 ? rv_amoswap_d(rs, rs, rd, 1, 1) : ++ rv_amoswap_w(rs, rs, rd, 1, 1), ctx); + if (!is64) + emit_zextw(rs, rs, ctx); + break; +diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h +index 5cc46e0dde620..9725586f42597 100644 +--- a/arch/s390/include/asm/gmap.h ++++ b/arch/s390/include/asm/gmap.h +@@ -146,7 +146,7 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start, + + void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4], + unsigned long gaddr, unsigned long vmaddr); +-int gmap_mark_unmergeable(void); ++int s390_disable_cow_sharing(void); + void s390_unlist_old_asce(struct gmap *gmap); + int s390_replace_asce(struct gmap *gmap); + void s390_uv_destroy_pfns(unsigned long count, unsigned long *pfns); +diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h +index bb1b4bef1878b..4c2dc7abc2858 100644 +--- a/arch/s390/include/asm/mmu.h ++++ b/arch/s390/include/asm/mmu.h +@@ -32,6 +32,11 @@ typedef struct { + unsigned int uses_skeys:1; + /* The mmu context uses CMM. */ + unsigned int uses_cmm:1; ++ /* ++ * The mmu context allows COW-sharing of memory pages (KSM, zeropage). ++ * Note that COW-sharing during fork() is currently always allowed. ++ */ ++ unsigned int allow_cow_sharing:1; + /* The gmaps associated with this context are allowed to use huge pages. */ + unsigned int allow_gmap_hpage_1m:1; + } mm_context_t; +diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h +index 929af18b09081..a7789a9f62186 100644 +--- a/arch/s390/include/asm/mmu_context.h ++++ b/arch/s390/include/asm/mmu_context.h +@@ -35,6 +35,7 @@ static inline int init_new_context(struct task_struct *tsk, + mm->context.has_pgste = 0; + mm->context.uses_skeys = 0; + mm->context.uses_cmm = 0; ++ mm->context.allow_cow_sharing = 1; + mm->context.allow_gmap_hpage_1m = 0; + #endif + switch (mm->context.asce_limit) { +diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h +index 60950e7a25f58..259c2439c2517 100644 +--- a/arch/s390/include/asm/pgtable.h ++++ b/arch/s390/include/asm/pgtable.h +@@ -566,10 +566,20 @@ static inline pud_t set_pud_bit(pud_t pud, pgprot_t prot) + } + + /* +- * In the case that a guest uses storage keys +- * faults should no longer be backed by zero pages ++ * As soon as the guest uses storage keys or enables PV, we deduplicate all ++ * mapped shared zeropages and prevent new shared zeropages from getting ++ * mapped. + */ +-#define mm_forbids_zeropage mm_has_pgste ++#define mm_forbids_zeropage mm_forbids_zeropage ++static inline int mm_forbids_zeropage(struct mm_struct *mm) ++{ ++#ifdef CONFIG_PGSTE ++ if (!mm->context.allow_cow_sharing) ++ return 1; ++#endif ++ return 0; ++} ++ + static inline int mm_uses_skeys(struct mm_struct *mm) + { + #ifdef CONFIG_PGSTE +diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S +index 48de296e8905c..fb9b32f936c45 100644 +--- a/arch/s390/kernel/vmlinux.lds.S ++++ b/arch/s390/kernel/vmlinux.lds.S +@@ -209,13 +209,13 @@ SECTIONS + .dynstr ALIGN(8) : { + *(.dynstr) + } +-#endif + .hash ALIGN(8) : { + *(.hash) + } + .gnu.hash ALIGN(8) : { + *(.gnu.hash) + } ++#endif + + . = ALIGN(PAGE_SIZE); + __init_end = .; /* freed after init ends here */ +diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c +index 7721eb522f43d..82e9631cd9efb 100644 +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -2631,9 +2631,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) + if (r) + break; + +- mmap_write_lock(current->mm); +- r = gmap_mark_unmergeable(); +- mmap_write_unlock(current->mm); ++ r = s390_disable_cow_sharing(); + if (r) + break; + +diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c +index 12d22a7fa32fd..474a25ca5c48f 100644 +--- a/arch/s390/mm/gmap.c ++++ b/arch/s390/mm/gmap.c +@@ -2549,41 +2549,6 @@ static inline void thp_split_mm(struct mm_struct *mm) + } + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + +-/* +- * Remove all empty zero pages from the mapping for lazy refaulting +- * - This must be called after mm->context.has_pgste is set, to avoid +- * future creation of zero pages +- * - This must be called after THP was disabled. +- * +- * mm contracts with s390, that even if mm were to remove a page table, +- * racing with the loop below and so causing pte_offset_map_lock() to fail, +- * it will never insert a page table containing empty zero pages once +- * mm_forbids_zeropage(mm) i.e. mm->context.has_pgste is set. +- */ +-static int __zap_zero_pages(pmd_t *pmd, unsigned long start, +- unsigned long end, struct mm_walk *walk) +-{ +- unsigned long addr; +- +- for (addr = start; addr != end; addr += PAGE_SIZE) { +- pte_t *ptep; +- spinlock_t *ptl; +- +- ptep = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); +- if (!ptep) +- break; +- if (is_zero_pfn(pte_pfn(*ptep))) +- ptep_xchg_direct(walk->mm, addr, ptep, __pte(_PAGE_INVALID)); +- pte_unmap_unlock(ptep, ptl); +- } +- return 0; +-} +- +-static const struct mm_walk_ops zap_zero_walk_ops = { +- .pmd_entry = __zap_zero_pages, +- .walk_lock = PGWALK_WRLOCK, +-}; +- + /* + * switch on pgstes for its userspace process (for kvm) + */ +@@ -2601,22 +2566,142 @@ int s390_enable_sie(void) + mm->context.has_pgste = 1; + /* split thp mappings and disable thp for future mappings */ + thp_split_mm(mm); +- walk_page_range(mm, 0, TASK_SIZE, &zap_zero_walk_ops, NULL); + mmap_write_unlock(mm); + return 0; + } + EXPORT_SYMBOL_GPL(s390_enable_sie); + +-int gmap_mark_unmergeable(void) ++static int find_zeropage_pte_entry(pte_t *pte, unsigned long addr, ++ unsigned long end, struct mm_walk *walk) ++{ ++ unsigned long *found_addr = walk->private; ++ ++ /* Return 1 of the page is a zeropage. */ ++ if (is_zero_pfn(pte_pfn(*pte))) { ++ /* ++ * Shared zeropage in e.g., a FS DAX mapping? We cannot do the ++ * right thing and likely don't care: FAULT_FLAG_UNSHARE ++ * currently only works in COW mappings, which is also where ++ * mm_forbids_zeropage() is checked. ++ */ ++ if (!is_cow_mapping(walk->vma->vm_flags)) ++ return -EFAULT; ++ ++ *found_addr = addr; ++ return 1; ++ } ++ return 0; ++} ++ ++static const struct mm_walk_ops find_zeropage_ops = { ++ .pte_entry = find_zeropage_pte_entry, ++ .walk_lock = PGWALK_WRLOCK, ++}; ++ ++/* ++ * Unshare all shared zeropages, replacing them by anonymous pages. Note that ++ * we cannot simply zap all shared zeropages, because this could later ++ * trigger unexpected userfaultfd missing events. ++ * ++ * This must be called after mm->context.allow_cow_sharing was ++ * set to 0, to avoid future mappings of shared zeropages. ++ * ++ * mm contracts with s390, that even if mm were to remove a page table, ++ * and racing with walk_page_range_vma() calling pte_offset_map_lock() ++ * would fail, it will never insert a page table containing empty zero ++ * pages once mm_forbids_zeropage(mm) i.e. ++ * mm->context.allow_cow_sharing is set to 0. ++ */ ++static int __s390_unshare_zeropages(struct mm_struct *mm) ++{ ++ struct vm_area_struct *vma; ++ VMA_ITERATOR(vmi, mm, 0); ++ unsigned long addr; ++ vm_fault_t fault; ++ int rc; ++ ++ for_each_vma(vmi, vma) { ++ /* ++ * We could only look at COW mappings, but it's more future ++ * proof to catch unexpected zeropages in other mappings and ++ * fail. ++ */ ++ if ((vma->vm_flags & VM_PFNMAP) || is_vm_hugetlb_page(vma)) ++ continue; ++ addr = vma->vm_start; ++ ++retry: ++ rc = walk_page_range_vma(vma, addr, vma->vm_end, ++ &find_zeropage_ops, &addr); ++ if (rc < 0) ++ return rc; ++ else if (!rc) ++ continue; ++ ++ /* addr was updated by find_zeropage_pte_entry() */ ++ fault = handle_mm_fault(vma, addr, ++ FAULT_FLAG_UNSHARE | FAULT_FLAG_REMOTE, ++ NULL); ++ if (fault & VM_FAULT_OOM) ++ return -ENOMEM; ++ /* ++ * See break_ksm(): even after handle_mm_fault() returned 0, we ++ * must start the lookup from the current address, because ++ * handle_mm_fault() may back out if there's any difficulty. ++ * ++ * VM_FAULT_SIGBUS and VM_FAULT_SIGSEGV are unexpected but ++ * maybe they could trigger in the future on concurrent ++ * truncation. In that case, the shared zeropage would be gone ++ * and we can simply retry and make progress. ++ */ ++ cond_resched(); ++ goto retry; ++ } ++ ++ return 0; ++} ++ ++static int __s390_disable_cow_sharing(struct mm_struct *mm) + { ++ int rc; ++ ++ if (!mm->context.allow_cow_sharing) ++ return 0; ++ ++ mm->context.allow_cow_sharing = 0; ++ ++ /* Replace all shared zeropages by anonymous pages. */ ++ rc = __s390_unshare_zeropages(mm); + /* + * Make sure to disable KSM (if enabled for the whole process or + * individual VMAs). Note that nothing currently hinders user space + * from re-enabling it. + */ +- return ksm_disable(current->mm); ++ if (!rc) ++ rc = ksm_disable(mm); ++ if (rc) ++ mm->context.allow_cow_sharing = 1; ++ return rc; ++} ++ ++/* ++ * Disable most COW-sharing of memory pages for the whole process: ++ * (1) Disable KSM and unmerge/unshare any KSM pages. ++ * (2) Disallow shared zeropages and unshare any zerpages that are mapped. ++ * ++ * Not that we currently don't bother with COW-shared pages that are shared ++ * with parent/child processes due to fork(). ++ */ ++int s390_disable_cow_sharing(void) ++{ ++ int rc; ++ ++ mmap_write_lock(current->mm); ++ rc = __s390_disable_cow_sharing(current->mm); ++ mmap_write_unlock(current->mm); ++ return rc; + } +-EXPORT_SYMBOL_GPL(gmap_mark_unmergeable); ++EXPORT_SYMBOL_GPL(s390_disable_cow_sharing); + + /* + * Enable storage key handling from now on and initialize the storage +@@ -2685,7 +2770,7 @@ int s390_enable_skey(void) + goto out_up; + + mm->context.uses_skeys = 1; +- rc = gmap_mark_unmergeable(); ++ rc = __s390_disable_cow_sharing(mm); + if (rc) { + mm->context.uses_skeys = 0; + goto out_up; +diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c +index 5af0402e94b88..1d168a98ae21b 100644 +--- a/arch/s390/net/bpf_jit_comp.c ++++ b/arch/s390/net/bpf_jit_comp.c +@@ -1427,8 +1427,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, + EMIT6_DISP_LH(0xeb000000, is32 ? (op32) : (op64), \ + (insn->imm & BPF_FETCH) ? src_reg : REG_W0, \ + src_reg, dst_reg, off); \ +- if (is32 && (insn->imm & BPF_FETCH)) \ +- EMIT_ZERO(src_reg); \ ++ if (insn->imm & BPF_FETCH) { \ ++ /* bcr 14,0 - see atomic_fetch_{add,and,or,xor}() */ \ ++ _EMIT2(0x07e0); \ ++ if (is32) \ ++ EMIT_ZERO(src_reg); \ ++ } \ + } while (0) + case BPF_ADD: + case BPF_ADD | BPF_FETCH: +diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c +index aed1ea8e2c2f0..74051b8ddf3e7 100644 +--- a/arch/sh/kernel/kprobes.c ++++ b/arch/sh/kernel/kprobes.c +@@ -44,17 +44,12 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) + if (OPCODE_RTE(opcode)) + return -EFAULT; /* Bad breakpoint */ + ++ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + p->opcode = opcode; + + return 0; + } + +-void __kprobes arch_copy_kprobe(struct kprobe *p) +-{ +- memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); +- p->opcode = *p->addr; +-} +- + void __kprobes arch_arm_kprobe(struct kprobe *p) + { + *p->addr = BREAKPOINT_INSTRUCTION; +diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S +index 3e07074e00981..06fed5a21e8ba 100644 +--- a/arch/sh/lib/checksum.S ++++ b/arch/sh/lib/checksum.S +@@ -33,7 +33,8 @@ + */ + + /* +- * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum); ++ * unsigned int csum_partial(const unsigned char *buf, int len, ++ * unsigned int sum); + */ + + .text +@@ -45,31 +46,11 @@ ENTRY(csum_partial) + * Fortunately, it is easy to convert 2-byte alignment to 4-byte + * alignment for the unrolled loop. + */ ++ mov r5, r1 + mov r4, r0 +- tst #3, r0 ! Check alignment. +- bt/s 2f ! Jump if alignment is ok. +- mov r4, r7 ! Keep a copy to check for alignment ++ tst #2, r0 ! Check alignment. ++ bt 2f ! Jump if alignment is ok. + ! +- tst #1, r0 ! Check alignment. +- bt 21f ! Jump if alignment is boundary of 2bytes. +- +- ! buf is odd +- tst r5, r5 +- add #-1, r5 +- bt 9f +- mov.b @r4+, r0 +- extu.b r0, r0 +- addc r0, r6 ! t=0 from previous tst +- mov r6, r0 +- shll8 r6 +- shlr16 r0 +- shlr8 r0 +- or r0, r6 +- mov r4, r0 +- tst #2, r0 +- bt 2f +-21: +- ! buf is 2 byte aligned (len could be 0) + add #-2, r5 ! Alignment uses up two bytes. + cmp/pz r5 ! + bt/s 1f ! Jump if we had at least two bytes. +@@ -77,17 +58,16 @@ ENTRY(csum_partial) + bra 6f + add #2, r5 ! r5 was < 2. Deal with it. + 1: ++ mov r5, r1 ! Save new len for later use. + mov.w @r4+, r0 + extu.w r0, r0 + addc r0, r6 + bf 2f + add #1, r6 + 2: +- ! buf is 4 byte aligned (len could be 0) +- mov r5, r1 + mov #-5, r0 +- shld r0, r1 +- tst r1, r1 ++ shld r0, r5 ++ tst r5, r5 + bt/s 4f ! if it's =0, go to 4f + clrt + .align 2 +@@ -109,31 +89,30 @@ ENTRY(csum_partial) + addc r0, r6 + addc r2, r6 + movt r0 +- dt r1 ++ dt r5 + bf/s 3b + cmp/eq #1, r0 +- ! here, we know r1==0 +- addc r1, r6 ! add carry to r6 ++ ! here, we know r5==0 ++ addc r5, r6 ! add carry to r6 + 4: +- mov r5, r0 ++ mov r1, r0 + and #0x1c, r0 + tst r0, r0 +- bt 6f +- ! 4 bytes or more remaining +- mov r0, r1 +- shlr2 r1 ++ bt/s 6f ++ mov r0, r5 ++ shlr2 r5 + mov #0, r2 + 5: + addc r2, r6 + mov.l @r4+, r2 + movt r0 +- dt r1 ++ dt r5 + bf/s 5b + cmp/eq #1, r0 + addc r2, r6 +- addc r1, r6 ! r1==0 here, so it means add carry-bit ++ addc r5, r6 ! r5==0 here, so it means add carry-bit + 6: +- ! 3 bytes or less remaining ++ mov r1, r5 + mov #3, r0 + and r0, r5 + tst r5, r5 +@@ -159,16 +138,6 @@ ENTRY(csum_partial) + mov #0, r0 + addc r0, r6 + 9: +- ! Check if the buffer was misaligned, if so realign sum +- mov r7, r0 +- tst #1, r0 +- bt 10f +- mov r6, r0 +- shll8 r6 +- shlr16 r0 +- shlr8 r0 +- or r0, r6 +-10: + rts + mov r6, r0 + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 928820e61cb50..f5b3d14ff385b 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -501,7 +501,7 @@ config X86_FRED + When enabled, try to use Flexible Return and Event Delivery + instead of the legacy SYSCALL/SYSENTER/IDT architecture for + ring transitions and exception/interrupt handling if the +- system supports. ++ system supports it. + + if X86_32 + config X86_BIGSMP +diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S +index bf4a10a5794f1..1dcb794c5479e 100644 +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -398,6 +398,11 @@ SYM_CODE_START(startup_64) + call sev_enable + #endif + ++ /* Preserve only the CR4 bits that must be preserved, and clear the rest */ ++ movq %cr4, %rax ++ andl $(X86_CR4_PAE | X86_CR4_MCE | X86_CR4_LA57), %eax ++ movq %rax, %cr4 ++ + /* + * configure_5level_paging() updates the number of paging levels using + * a trampoline in 32-bit addressable memory if the current number does +diff --git a/arch/x86/crypto/nh-avx2-x86_64.S b/arch/x86/crypto/nh-avx2-x86_64.S +index ef73a3ab87263..791386d9a83aa 100644 +--- a/arch/x86/crypto/nh-avx2-x86_64.S ++++ b/arch/x86/crypto/nh-avx2-x86_64.S +@@ -154,5 +154,6 @@ SYM_TYPED_FUNC_START(nh_avx2) + vpaddq T1, T0, T0 + vpaddq T4, T0, T0 + vmovdqu T0, (HASH) ++ vzeroupper + RET + SYM_FUNC_END(nh_avx2) +diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S +index 9918212faf914..0ffb072be9561 100644 +--- a/arch/x86/crypto/sha256-avx2-asm.S ++++ b/arch/x86/crypto/sha256-avx2-asm.S +@@ -716,6 +716,7 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx) + popq %r13 + popq %r12 + popq %rbx ++ vzeroupper + RET + SYM_FUNC_END(sha256_transform_rorx) + +diff --git a/arch/x86/crypto/sha512-avx2-asm.S b/arch/x86/crypto/sha512-avx2-asm.S +index f08496cd68708..24973f42c43ff 100644 +--- a/arch/x86/crypto/sha512-avx2-asm.S ++++ b/arch/x86/crypto/sha512-avx2-asm.S +@@ -680,6 +680,7 @@ SYM_TYPED_FUNC_START(sha512_transform_rorx) + pop %r12 + pop %rbx + ++ vzeroupper + RET + SYM_FUNC_END(sha512_transform_rorx) + +diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h +index 44b08b53ab32f..c1d6cd58f8094 100644 +--- a/arch/x86/include/asm/cmpxchg_64.h ++++ b/arch/x86/include/asm/cmpxchg_64.h +@@ -62,7 +62,7 @@ static __always_inline u128 arch_cmpxchg128_local(volatile u128 *ptr, u128 old, + asm volatile(_lock "cmpxchg16b %[ptr]" \ + CC_SET(e) \ + : CC_OUT(e) (ret), \ +- [ptr] "+m" (*ptr), \ ++ [ptr] "+m" (*(_ptr)), \ + "+a" (o.low), "+d" (o.high) \ + : "b" (n.low), "c" (n.high) \ + : "memory"); \ +diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h +index 9abb8cc4cd474..b786449626267 100644 +--- a/arch/x86/include/asm/pgtable_types.h ++++ b/arch/x86/include/asm/pgtable_types.h +@@ -567,6 +567,8 @@ static inline void update_page_count(int level, unsigned long pages) { } + extern pte_t *lookup_address(unsigned long address, unsigned int *level); + extern pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, + unsigned int *level); ++pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address, ++ unsigned int *level, bool *nx, bool *rw); + extern pmd_t *lookup_pmd_address(unsigned long address); + extern phys_addr_t slow_virt_to_phys(void *__address); + extern int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, +diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h +index 1be13b2dfe8bf..64df897c0ee30 100644 +--- a/arch/x86/include/asm/sparsemem.h ++++ b/arch/x86/include/asm/sparsemem.h +@@ -37,8 +37,6 @@ extern int phys_to_target_node(phys_addr_t start); + #define phys_to_target_node phys_to_target_node + extern int memory_add_physaddr_to_nid(u64 start); + #define memory_add_physaddr_to_nid memory_add_physaddr_to_nid +-extern int numa_fill_memblks(u64 start, u64 end); +-#define numa_fill_memblks numa_fill_memblks + #endif + #endif /* __ASSEMBLY__ */ + +diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c +index 13b45b9c806da..620f0af713ca2 100644 +--- a/arch/x86/kernel/cpu/microcode/amd.c ++++ b/arch/x86/kernel/cpu/microcode/amd.c +@@ -465,7 +465,7 @@ static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, siz + return !__apply_microcode_amd(mc); + } + +-static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family) ++static bool get_builtin_microcode(struct cpio_data *cp, u8 family) + { + char fw_name[36] = "amd-ucode/microcode_amd.bin"; + struct firmware fw; +diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c +index 1123ef3ccf901..4334033658edf 100644 +--- a/arch/x86/kernel/tsc_sync.c ++++ b/arch/x86/kernel/tsc_sync.c +@@ -193,11 +193,9 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu) + cur->warned = false; + + /* +- * If a non-zero TSC value for socket 0 may be valid then the default +- * adjusted value cannot assumed to be zero either. ++ * The default adjust value cannot be assumed to be zero on any socket. + */ +- if (tsc_async_resets) +- cur->adjusted = bootval; ++ cur->adjusted = bootval; + + /* + * Check whether this CPU is the first in a package to come up. In +diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt +index 12af572201a29..da9347552be69 100644 +--- a/arch/x86/lib/x86-opcode-map.txt ++++ b/arch/x86/lib/x86-opcode-map.txt +@@ -148,7 +148,7 @@ AVXcode: + 65: SEG=GS (Prefix) + 66: Operand-Size (Prefix) + 67: Address-Size (Prefix) +-68: PUSH Iz (d64) ++68: PUSH Iz + 69: IMUL Gv,Ev,Iz + 6a: PUSH Ib (d64) + 6b: IMUL Gv,Ev,Ib +@@ -698,10 +698,10 @@ AVXcode: 2 + 4d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev) + 4e: vrsqrt14ps/d Vpd,Wpd (66),(ev) + 4f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev) +-50: vpdpbusd Vx,Hx,Wx (66),(ev) +-51: vpdpbusds Vx,Hx,Wx (66),(ev) +-52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66),(ev) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev) +-53: vpdpwssds Vx,Hx,Wx (66),(ev) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev) ++50: vpdpbusd Vx,Hx,Wx (66) ++51: vpdpbusds Vx,Hx,Wx (66) ++52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev) ++53: vpdpwssds Vx,Hx,Wx (66) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev) + 54: vpopcntb/w Vx,Wx (66),(ev) + 55: vpopcntd/q Vx,Wx (66),(ev) + 58: vpbroadcastd Vx,Wx (66),(v) +diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c +index 65e9a6e391c04..ce84ba86e69e9 100644 +--- a/arch/x86/mm/numa.c ++++ b/arch/x86/mm/numa.c +@@ -929,6 +929,8 @@ int memory_add_physaddr_to_nid(u64 start) + } + EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); + ++#endif ++ + static int __init cmp_memblk(const void *a, const void *b) + { + const struct numa_memblk *ma = *(const struct numa_memblk **)a; +@@ -1001,5 +1003,3 @@ int __init numa_fill_memblks(u64 start, u64 end) + } + return 0; + } +- +-#endif +diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c +index 80c9037ffadff..19fdfbb171ed6 100644 +--- a/arch/x86/mm/pat/set_memory.c ++++ b/arch/x86/mm/pat/set_memory.c +@@ -619,7 +619,8 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start, + * Validate strict W^X semantics. + */ + static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long start, +- unsigned long pfn, unsigned long npg) ++ unsigned long pfn, unsigned long npg, ++ bool nx, bool rw) + { + unsigned long end; + +@@ -641,6 +642,10 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star + if ((pgprot_val(new) & (_PAGE_RW | _PAGE_NX)) != _PAGE_RW) + return new; + ++ /* Non-leaf translation entries can disable writing or execution. */ ++ if (!rw || nx) ++ return new; ++ + end = start + npg * PAGE_SIZE - 1; + WARN_ONCE(1, "CPA detected W^X violation: %016llx -> %016llx range: 0x%016lx - 0x%016lx PFN %lx\n", + (unsigned long long)pgprot_val(old), +@@ -657,20 +662,26 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star + + /* + * Lookup the page table entry for a virtual address in a specific pgd. +- * Return a pointer to the entry and the level of the mapping. ++ * Return a pointer to the entry, the level of the mapping, and the effective ++ * NX and RW bits of all page table levels. + */ +-pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, +- unsigned int *level) ++pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address, ++ unsigned int *level, bool *nx, bool *rw) + { + p4d_t *p4d; + pud_t *pud; + pmd_t *pmd; + + *level = PG_LEVEL_NONE; ++ *nx = false; ++ *rw = true; + + if (pgd_none(*pgd)) + return NULL; + ++ *nx |= pgd_flags(*pgd) & _PAGE_NX; ++ *rw &= pgd_flags(*pgd) & _PAGE_RW; ++ + p4d = p4d_offset(pgd, address); + if (p4d_none(*p4d)) + return NULL; +@@ -679,6 +690,9 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, + if (p4d_leaf(*p4d) || !p4d_present(*p4d)) + return (pte_t *)p4d; + ++ *nx |= p4d_flags(*p4d) & _PAGE_NX; ++ *rw &= p4d_flags(*p4d) & _PAGE_RW; ++ + pud = pud_offset(p4d, address); + if (pud_none(*pud)) + return NULL; +@@ -687,6 +701,9 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, + if (pud_leaf(*pud) || !pud_present(*pud)) + return (pte_t *)pud; + ++ *nx |= pud_flags(*pud) & _PAGE_NX; ++ *rw &= pud_flags(*pud) & _PAGE_RW; ++ + pmd = pmd_offset(pud, address); + if (pmd_none(*pmd)) + return NULL; +@@ -695,11 +712,26 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, + if (pmd_leaf(*pmd) || !pmd_present(*pmd)) + return (pte_t *)pmd; + ++ *nx |= pmd_flags(*pmd) & _PAGE_NX; ++ *rw &= pmd_flags(*pmd) & _PAGE_RW; ++ + *level = PG_LEVEL_4K; + + return pte_offset_kernel(pmd, address); + } + ++/* ++ * Lookup the page table entry for a virtual address in a specific pgd. ++ * Return a pointer to the entry and the level of the mapping. ++ */ ++pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, ++ unsigned int *level) ++{ ++ bool nx, rw; ++ ++ return lookup_address_in_pgd_attr(pgd, address, level, &nx, &rw); ++} ++ + /* + * Lookup the page table entry for a virtual address. Return a pointer + * to the entry and the level of the mapping. +@@ -715,13 +747,16 @@ pte_t *lookup_address(unsigned long address, unsigned int *level) + EXPORT_SYMBOL_GPL(lookup_address); + + static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address, +- unsigned int *level) ++ unsigned int *level, bool *nx, bool *rw) + { +- if (cpa->pgd) +- return lookup_address_in_pgd(cpa->pgd + pgd_index(address), +- address, level); ++ pgd_t *pgd; ++ ++ if (!cpa->pgd) ++ pgd = pgd_offset_k(address); ++ else ++ pgd = cpa->pgd + pgd_index(address); + +- return lookup_address(address, level); ++ return lookup_address_in_pgd_attr(pgd, address, level, nx, rw); + } + + /* +@@ -849,12 +884,13 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address, + pgprot_t old_prot, new_prot, req_prot, chk_prot; + pte_t new_pte, *tmp; + enum pg_level level; ++ bool nx, rw; + + /* + * Check for races, another CPU might have split this page + * up already: + */ +- tmp = _lookup_address_cpa(cpa, address, &level); ++ tmp = _lookup_address_cpa(cpa, address, &level, &nx, &rw); + if (tmp != kpte) + return 1; + +@@ -965,7 +1001,8 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address, + new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages, + psize, CPA_DETECT); + +- new_prot = verify_rwx(old_prot, new_prot, lpaddr, old_pfn, numpages); ++ new_prot = verify_rwx(old_prot, new_prot, lpaddr, old_pfn, numpages, ++ nx, rw); + + /* + * If there is a conflict, split the large page. +@@ -1046,6 +1083,7 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address, + pte_t *pbase = (pte_t *)page_address(base); + unsigned int i, level; + pgprot_t ref_prot; ++ bool nx, rw; + pte_t *tmp; + + spin_lock(&pgd_lock); +@@ -1053,7 +1091,7 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address, + * Check for races, another CPU might have split this page + * up for us already: + */ +- tmp = _lookup_address_cpa(cpa, address, &level); ++ tmp = _lookup_address_cpa(cpa, address, &level, &nx, &rw); + if (tmp != kpte) { + spin_unlock(&pgd_lock); + return 1; +@@ -1594,10 +1632,11 @@ static int __change_page_attr(struct cpa_data *cpa, int primary) + int do_split, err; + unsigned int level; + pte_t *kpte, old_pte; ++ bool nx, rw; + + address = __cpa_addr(cpa, cpa->curpage); + repeat: +- kpte = _lookup_address_cpa(cpa, address, &level); ++ kpte = _lookup_address_cpa(cpa, address, &level, &nx, &rw); + if (!kpte) + return __cpa_process_fault(cpa, address, primary); + +@@ -1619,7 +1658,8 @@ static int __change_page_attr(struct cpa_data *cpa, int primary) + new_prot = static_protections(new_prot, address, pfn, 1, 0, + CPA_PROTECT); + +- new_prot = verify_rwx(old_prot, new_prot, address, pfn, 1); ++ new_prot = verify_rwx(old_prot, new_prot, address, pfn, 1, ++ nx, rw); + + new_prot = pgprot_clear_protnone_bits(new_prot); + +diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile +index bc31863c5ee63..a18591f6e6d94 100644 +--- a/arch/x86/purgatory/Makefile ++++ b/arch/x86/purgatory/Makefile +@@ -42,7 +42,8 @@ KCOV_INSTRUMENT := n + # make up the standalone purgatory.ro + + PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel +-PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss -g0 ++PURGATORY_CFLAGS := -mcmodel=small -ffreestanding -fno-zero-initialized-in-bss -g0 ++PURGATORY_CFLAGS += -fpic -fvisibility=hidden + PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING + PURGATORY_CFLAGS += -fno-stack-protector + +diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c +index b029fb81ebeee..e7a44a7f617fb 100644 +--- a/arch/x86/tools/relocs.c ++++ b/arch/x86/tools/relocs.c +@@ -746,6 +746,15 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, + if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { + continue; + } ++ ++ /* ++ * Do not perform relocations in .notes sections; any ++ * values there are meant for pre-boot consumption (e.g. ++ * startup_xen). ++ */ ++ if (sec_applies->shdr.sh_type == SHT_NOTE) ++ continue; ++ + sh_symtab = sec_symtab->symtab; + sym_strtab = sec_symtab->link->strtab; + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { +diff --git a/block/blk-core.c b/block/blk-core.c +index b795ac177281a..6fcf8ed5fc1f1 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -987,10 +987,11 @@ void update_io_ticks(struct block_device *part, unsigned long now, bool end) + unsigned long stamp; + again: + stamp = READ_ONCE(part->bd_stamp); +- if (unlikely(time_after(now, stamp))) { +- if (likely(try_cmpxchg(&part->bd_stamp, &stamp, now))) +- __part_stat_add(part, io_ticks, end ? now - stamp : 1); +- } ++ if (unlikely(time_after(now, stamp)) && ++ likely(try_cmpxchg(&part->bd_stamp, &stamp, now)) && ++ (end || part_in_flight(part))) ++ __part_stat_add(part, io_ticks, now - stamp); ++ + if (part->bd_partno) { + part = bdev_whole(part); + goto again; +diff --git a/block/blk-merge.c b/block/blk-merge.c +index 4e3483a16b757..ae61a9c2fc93c 100644 +--- a/block/blk-merge.c ++++ b/block/blk-merge.c +@@ -779,6 +779,8 @@ static void blk_account_io_merge_request(struct request *req) + if (blk_do_io_stat(req)) { + part_stat_lock(); + part_stat_inc(req->part, merges[op_stat_group(req_op(req))]); ++ part_stat_local_dec(req->part, ++ in_flight[op_is_write(req_op(req))]); + part_stat_unlock(); + } + } +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 32afb87efbd0e..5ac2087b05630 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -997,6 +997,8 @@ static inline void blk_account_io_done(struct request *req, u64 now) + update_io_ticks(req->part, jiffies, true); + part_stat_inc(req->part, ios[sgrp]); + part_stat_add(req->part, nsecs[sgrp], now - req->start_time_ns); ++ part_stat_local_dec(req->part, ++ in_flight[op_is_write(req_op(req))]); + part_stat_unlock(); + } + } +@@ -1019,6 +1021,8 @@ static inline void blk_account_io_start(struct request *req) + + part_stat_lock(); + update_io_ticks(req->part, jiffies, false); ++ part_stat_local_inc(req->part, ++ in_flight[op_is_write(req_op(req))]); + part_stat_unlock(); + } + } +diff --git a/block/blk.h b/block/blk.h +index d9f584984bc44..da5dbc6b13068 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -357,6 +357,7 @@ static inline bool blk_do_io_stat(struct request *rq) + } + + void update_io_ticks(struct block_device *part, unsigned long now, bool end); ++unsigned int part_in_flight(struct block_device *part); + + static inline void req_set_nomerge(struct request_queue *q, struct request *req) + { +diff --git a/block/fops.c b/block/fops.c +index 679d9b752fe82..df2c68d3f198e 100644 +--- a/block/fops.c ++++ b/block/fops.c +@@ -390,7 +390,7 @@ static int blkdev_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + + iomap->bdev = bdev; + iomap->offset = ALIGN_DOWN(offset, bdev_logical_block_size(bdev)); +- if (iomap->offset >= isize) ++ if (offset >= isize) + return -EIO; + iomap->type = IOMAP_MAPPED; + iomap->addr = iomap->offset; +diff --git a/block/genhd.c b/block/genhd.c +index 52a4521df067b..345d80ab9791b 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -118,7 +118,7 @@ static void part_stat_read_all(struct block_device *part, + } + } + +-static unsigned int part_in_flight(struct block_device *part) ++unsigned int part_in_flight(struct block_device *part) + { + unsigned int inflight = 0; + int cpu; +diff --git a/block/partitions/cmdline.c b/block/partitions/cmdline.c +index c03bc105e5753..152c85df92b20 100644 +--- a/block/partitions/cmdline.c ++++ b/block/partitions/cmdline.c +@@ -70,8 +70,8 @@ static int parse_subpart(struct cmdline_subpart **subpart, char *partdef) + } + + if (*partdef == '(') { +- int length; +- char *next = strchr(++partdef, ')'); ++ partdef++; ++ char *next = strsep(&partdef, ")"); + + if (!next) { + pr_warn("cmdline partition format is invalid."); +@@ -79,11 +79,7 @@ static int parse_subpart(struct cmdline_subpart **subpart, char *partdef) + goto fail; + } + +- length = min_t(int, next - partdef, +- sizeof(new_subpart->name) - 1); +- strscpy(new_subpart->name, partdef, length); +- +- partdef = ++next; ++ strscpy(new_subpart->name, next, sizeof(new_subpart->name)); + } else + new_subpart->name[0] = '\0'; + +@@ -117,14 +113,12 @@ static void free_subpart(struct cmdline_parts *parts) + } + } + +-static int parse_parts(struct cmdline_parts **parts, const char *bdevdef) ++static int parse_parts(struct cmdline_parts **parts, char *bdevdef) + { + int ret = -EINVAL; + char *next; +- int length; + struct cmdline_subpart **next_subpart; + struct cmdline_parts *newparts; +- char buf[BDEVNAME_SIZE + 32 + 4]; + + *parts = NULL; + +@@ -132,28 +126,19 @@ static int parse_parts(struct cmdline_parts **parts, const char *bdevdef) + if (!newparts) + return -ENOMEM; + +- next = strchr(bdevdef, ':'); ++ next = strsep(&bdevdef, ":"); + if (!next) { + pr_warn("cmdline partition has no block device."); + goto fail; + } + +- length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1); +- strscpy(newparts->name, bdevdef, length); ++ strscpy(newparts->name, next, sizeof(newparts->name)); + newparts->nr_subparts = 0; + + next_subpart = &newparts->subpart; + +- while (next && *(++next)) { +- bdevdef = next; +- next = strchr(bdevdef, ','); +- +- length = (!next) ? (sizeof(buf) - 1) : +- min_t(int, next - bdevdef, sizeof(buf) - 1); +- +- strscpy(buf, bdevdef, length); +- +- ret = parse_subpart(next_subpart, buf); ++ while ((next = strsep(&bdevdef, ","))) { ++ ret = parse_subpart(next_subpart, next); + if (ret) + goto fail; + +@@ -199,24 +184,17 @@ static int cmdline_parts_parse(struct cmdline_parts **parts, + + *parts = NULL; + +- next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL); ++ pbuf = buf = kstrdup(cmdline, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + next_parts = parts; + +- while (next && *pbuf) { +- next = strchr(pbuf, ';'); +- if (next) +- *next = '\0'; +- +- ret = parse_parts(next_parts, pbuf); ++ while ((next = strsep(&pbuf, ";"))) { ++ ret = parse_parts(next_parts, next); + if (ret) + goto fail; + +- if (next) +- pbuf = ++next; +- + next_parts = &(*next_parts)->next_parts; + } + +@@ -250,7 +228,6 @@ static struct cmdline_parts *bdev_parts; + static int add_part(int slot, struct cmdline_subpart *subpart, + struct parsed_partitions *state) + { +- int label_min; + struct partition_meta_info *info; + char tmp[sizeof(info->volname) + 4]; + +@@ -262,9 +239,7 @@ static int add_part(int slot, struct cmdline_subpart *subpart, + + info = &state->parts[slot].info; + +- label_min = min_t(int, sizeof(info->volname) - 1, +- sizeof(subpart->name)); +- strscpy(info->volname, subpart->name, label_min); ++ strscpy(info->volname, subpart->name, sizeof(info->volname)); + + snprintf(tmp, sizeof(tmp), "(%s)", info->volname); + strlcat(state->pp_buf, tmp, PAGE_SIZE); +diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig +index 59ec726b7c770..684767ab23e24 100644 +--- a/crypto/asymmetric_keys/Kconfig ++++ b/crypto/asymmetric_keys/Kconfig +@@ -15,6 +15,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select MPILIB + select CRYPTO_HASH_INFO + select CRYPTO_AKCIPHER ++ select CRYPTO_SIG + select CRYPTO_HASH + help + This option provides support for asymmetric public key type handling. +@@ -85,5 +86,7 @@ config FIPS_SIGNATURE_SELFTEST + depends on ASYMMETRIC_KEY_TYPE + depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER + depends on X509_CERTIFICATE_PARSER ++ depends on CRYPTO_RSA ++ depends on CRYPTO_SHA256 + + endif # ASYMMETRIC_KEY_TYPE +diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c +index 736c2eb8c0f37..f677ad2177c2f 100644 +--- a/drivers/accessibility/speakup/main.c ++++ b/drivers/accessibility/speakup/main.c +@@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *vc) + } + attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr); + buf[cnt++] = attr_ch; +- while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) { ++ while (tmpx < vc->vc_cols - 1 && cnt < ARRAY_SIZE(buf) - 1) { + tmp_pos += 2; + tmpx++; + ch = get_char(vc, (u_short *)tmp_pos, &temp); +diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c +index 04e273167e92a..8e01792228d1e 100644 +--- a/drivers/acpi/acpi_lpss.c ++++ b/drivers/acpi/acpi_lpss.c +@@ -325,6 +325,7 @@ static const struct lpss_device_desc bsw_i2c_dev_desc = { + + static const struct property_entry bsw_spi_properties[] = { + PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BSW_SSP), ++ PROPERTY_ENTRY_U32("num-cs", 2), + { } + }; + +diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile +index 30f3fc13c29d1..8d18af396de92 100644 +--- a/drivers/acpi/acpica/Makefile ++++ b/drivers/acpi/acpica/Makefile +@@ -5,6 +5,7 @@ + + ccflags-y := -D_LINUX -DBUILDING_ACPICA + ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT ++CFLAGS_tbfind.o += $(call cc-disable-warning, stringop-truncation) + + # use acpi.o to put all files here into acpi.o modparam namespace + obj-y += acpi.o +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index d9fa730416f19..a87b10eef77df 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -316,9 +316,14 @@ static void acpi_bus_osc_negotiate_platform_control(void) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_PROCESSOR)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; ++ if (IS_ENABLED(CONFIG_ACPI_THERMAL)) ++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT; + + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; ++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_OVER_16_PSTATES_SUPPORT; ++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GED_SUPPORT; ++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_IRQ_RESOURCE_SOURCE_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_PRMT)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_FFH)) +diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c +index e45e64993c504..3b09fd39eeb4f 100644 +--- a/drivers/acpi/numa/srat.c ++++ b/drivers/acpi/numa/srat.c +@@ -208,6 +208,11 @@ int __init srat_disabled(void) + return acpi_numa < 0; + } + ++__weak int __init numa_fill_memblks(u64 start, u64 end) ++{ ++ return NUMA_NO_MEMBLK; ++} ++ + #if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) + /* + * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index ed33cf7192d21..eed63f95e89d0 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -2113,6 +2113,8 @@ static void __exit null_exit(void) + + if (tag_set.ops) + blk_mq_free_tag_set(&tag_set); ++ ++ mutex_destroy(&lock); + } + + module_init(null_init); +diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c +index 9658b33c824a7..18f34998a1204 100644 +--- a/drivers/bluetooth/btmrvl_main.c ++++ b/drivers/bluetooth/btmrvl_main.c +@@ -121,13 +121,6 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) + ((event->data[2] == MODULE_BROUGHT_UP) || + (event->data[2] == MODULE_ALREADY_UP)) ? + "Bring-up succeed" : "Bring-up failed"); +- +- if (event->length > 3 && event->data[3]) +- priv->btmrvl_dev.dev_type = HCI_AMP; +- else +- priv->btmrvl_dev.dev_type = HCI_PRIMARY; +- +- BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type); + } else if (priv->btmrvl_dev.sendcmdflag && + event->data[1] == MODULE_SHUTDOWN_REQ) { + BT_DBG("EVENT:%s", (event->data[2]) ? +@@ -686,8 +679,6 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) + hdev->wakeup = btmrvl_wakeup; + SET_HCIDEV_DEV(hdev, &card->func->dev); + +- hdev->dev_type = priv->btmrvl_dev.dev_type; +- + ret = hci_register_dev(hdev); + if (ret < 0) { + BT_ERR("Can not register HCI device"); +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c +index 638074992c829..35fb26cbf2294 100644 +--- a/drivers/bluetooth/btqca.c ++++ b/drivers/bluetooth/btqca.c +@@ -148,8 +148,10 @@ static int qca_read_fw_build_info(struct hci_dev *hdev) + } + + build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL); +- if (!build_label) ++ if (!build_label) { ++ err = -ENOMEM; + goto out; ++ } + + hci_set_fw_info(hdev, "%s", build_label); + +diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c +index 634cf8f5ed2db..0c91d7635ac39 100644 +--- a/drivers/bluetooth/btrsi.c ++++ b/drivers/bluetooth/btrsi.c +@@ -134,7 +134,6 @@ static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops) + hdev->bus = HCI_USB; + + hci_set_drvdata(hdev, h_adapter); +- hdev->dev_type = HCI_PRIMARY; + hdev->open = rsi_hci_open; + hdev->close = rsi_hci_close; + hdev->flush = rsi_hci_flush; +diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c +index f19d31ee37ea8..fdcfe9c50313e 100644 +--- a/drivers/bluetooth/btsdio.c ++++ b/drivers/bluetooth/btsdio.c +@@ -32,9 +32,6 @@ static const struct sdio_device_id btsdio_table[] = { + /* Generic Bluetooth Type-B SDIO device */ + { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) }, + +- /* Generic Bluetooth AMP controller */ +- { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) }, +- + { } /* Terminating entry */ + }; + +@@ -319,11 +316,6 @@ static int btsdio_probe(struct sdio_func *func, + hdev->bus = HCI_SDIO; + hci_set_drvdata(hdev, data); + +- if (id->class == SDIO_CLASS_BT_AMP) +- hdev->dev_type = HCI_AMP; +- else +- hdev->dev_type = HCI_PRIMARY; +- + data->hdev = hdev; + + SET_HCIDEV_DEV(hdev, &func->dev); +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 01b99471d1bbe..fb716849b60f3 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4332,11 +4332,6 @@ static int btusb_probe(struct usb_interface *intf, + hdev->bus = HCI_USB; + hci_set_drvdata(hdev, data); + +- if (id->driver_info & BTUSB_AMP) +- hdev->dev_type = HCI_AMP; +- else +- hdev->dev_type = HCI_PRIMARY; +- + data->hdev = hdev; + + SET_HCIDEV_DEV(hdev, &intf->dev); +diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c +index 9a7243d5db71f..0c2f15235b4cd 100644 +--- a/drivers/bluetooth/hci_bcm4377.c ++++ b/drivers/bluetooth/hci_bcm4377.c +@@ -2361,7 +2361,6 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id) + bcm4377->hdev = hdev; + + hdev->bus = HCI_PCI; +- hdev->dev_type = HCI_PRIMARY; + hdev->open = bcm4377_hci_open; + hdev->close = bcm4377_hci_close; + hdev->send = bcm4377_hci_send_frame; +diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c +index a26367e9fb197..17a2f158a0dfa 100644 +--- a/drivers/bluetooth/hci_ldisc.c ++++ b/drivers/bluetooth/hci_ldisc.c +@@ -667,11 +667,6 @@ static int hci_uart_register_dev(struct hci_uart *hu) + if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) + set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + +- if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) +- hdev->dev_type = HCI_AMP; +- else +- hdev->dev_type = HCI_PRIMARY; +- + /* Only call open() for the protocol after hdev is fully initialized as + * open() (or a timer/workqueue it starts) may attempt to reference it. + */ +@@ -722,7 +717,6 @@ static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags) + { + unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) | + BIT(HCI_UART_RESET_ON_INIT) | +- BIT(HCI_UART_CREATE_AMP) | + BIT(HCI_UART_INIT_PENDING) | + BIT(HCI_UART_EXT_CONFIG) | + BIT(HCI_UART_VND_DETECT); +diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c +index 85c0d9b68f5f7..89a22e9b3253a 100644 +--- a/drivers/bluetooth/hci_serdev.c ++++ b/drivers/bluetooth/hci_serdev.c +@@ -366,11 +366,6 @@ int hci_uart_register_device_priv(struct hci_uart *hu, + if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) + set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); + +- if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) +- hdev->dev_type = HCI_AMP; +- else +- hdev->dev_type = HCI_PRIMARY; +- + if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) + return 0; + +diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h +index 68c8c7e95d64d..00bf7ae82c5b7 100644 +--- a/drivers/bluetooth/hci_uart.h ++++ b/drivers/bluetooth/hci_uart.h +@@ -37,7 +37,6 @@ + + #define HCI_UART_RAW_DEVICE 0 + #define HCI_UART_RESET_ON_INIT 1 +-#define HCI_UART_CREATE_AMP 2 + #define HCI_UART_INIT_PENDING 3 + #define HCI_UART_EXT_CONFIG 4 + #define HCI_UART_VND_DETECT 5 +diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c +index 572d68d52965f..28750a40f0ed5 100644 +--- a/drivers/bluetooth/hci_vhci.c ++++ b/drivers/bluetooth/hci_vhci.c +@@ -384,17 +384,10 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) + { + struct hci_dev *hdev; + struct sk_buff *skb; +- __u8 dev_type; + + if (data->hdev) + return -EBADFD; + +- /* bits 0-1 are dev_type (Primary or AMP) */ +- dev_type = opcode & 0x03; +- +- if (dev_type != HCI_PRIMARY && dev_type != HCI_AMP) +- return -EINVAL; +- + /* bits 2-5 are reserved (must be zero) */ + if (opcode & 0x3c) + return -EINVAL; +@@ -412,7 +405,6 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) + data->hdev = hdev; + + hdev->bus = HCI_VIRTUAL; +- hdev->dev_type = dev_type; + hci_set_drvdata(hdev, data); + + hdev->open = vhci_open_dev; +@@ -634,7 +626,7 @@ static void vhci_open_timeout(struct work_struct *work) + struct vhci_data *data = container_of(work, struct vhci_data, + open_timeout.work); + +- vhci_create_device(data, amp ? HCI_AMP : HCI_PRIMARY); ++ vhci_create_device(data, 0x00); + } + + static int vhci_open(struct inode *inode, struct file *file) +diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c +index 2ac70b560c46d..18208e152a367 100644 +--- a/drivers/bluetooth/virtio_bt.c ++++ b/drivers/bluetooth/virtio_bt.c +@@ -274,7 +274,6 @@ static int virtbt_probe(struct virtio_device *vdev) + + switch (type) { + case VIRTIO_BT_CONFIG_TYPE_PRIMARY: +- case VIRTIO_BT_CONFIG_TYPE_AMP: + break; + default: + return -EINVAL; +@@ -303,7 +302,6 @@ static int virtbt_probe(struct virtio_device *vdev) + vbt->hdev = hdev; + + hdev->bus = HCI_VIRTIO; +- hdev->dev_type = type; + hci_set_drvdata(hdev, vbt); + + hdev->open = virtbt_open; +diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c +index 379bc245c5202..0e903d6e22e30 100644 +--- a/drivers/char/hw_random/stm32-rng.c ++++ b/drivers/char/hw_random/stm32-rng.c +@@ -220,7 +220,8 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) + if (err && i > RNG_NB_RECOVER_TRIES) { + dev_err((struct device *)priv->rng.priv, + "Couldn't recover from seed error\n"); +- return -ENOTRECOVERABLE; ++ retval = -ENOTRECOVERABLE; ++ goto exit_rpm; + } + + continue; +@@ -238,7 +239,8 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) + if (err && i > RNG_NB_RECOVER_TRIES) { + dev_err((struct device *)priv->rng.priv, + "Couldn't recover from seed error"); +- return -ENOTRECOVERABLE; ++ retval = -ENOTRECOVERABLE; ++ goto exit_rpm; + } + + continue; +@@ -250,6 +252,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) + max -= sizeof(u32); + } + ++exit_rpm: + pm_runtime_mark_last_busy((struct device *) priv->rng.priv); + pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv); + +@@ -353,13 +356,15 @@ static int stm32_rng_init(struct hwrng *rng) + err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, reg, + reg & RNG_SR_DRDY, + 10, 100000); +- if (err | (reg & ~RNG_SR_DRDY)) { ++ if (err || (reg & ~RNG_SR_DRDY)) { + clk_disable_unprepare(priv->clk); + dev_err((struct device *)priv->rng.priv, + "%s: timeout:%x SR: %x!\n", __func__, err, reg); + return -EINVAL; + } + ++ clk_disable_unprepare(priv->clk); ++ + return 0; + } + +@@ -384,6 +389,11 @@ static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev) + static int __maybe_unused stm32_rng_suspend(struct device *dev) + { + struct stm32_rng_private *priv = dev_get_drvdata(dev); ++ int err; ++ ++ err = clk_prepare_enable(priv->clk); ++ if (err) ++ return err; + + if (priv->data->has_cond_reset) { + priv->pm_conf.nscr = readl_relaxed(priv->base + RNG_NSCR); +@@ -465,6 +475,8 @@ static int __maybe_unused stm32_rng_resume(struct device *dev) + writel_relaxed(reg, priv->base + RNG_CR); + } + ++ clk_disable_unprepare(priv->clk); ++ + return 0; + } + +diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c +index 53e21ac302e6d..4c3a5e4eb77ac 100644 +--- a/drivers/clk/clk-renesas-pcie.c ++++ b/drivers/clk/clk-renesas-pcie.c +@@ -25,10 +25,12 @@ + #define RS9_REG_SS_AMP_0V7 0x1 + #define RS9_REG_SS_AMP_0V8 0x2 + #define RS9_REG_SS_AMP_0V9 0x3 ++#define RS9_REG_SS_AMP_DEFAULT RS9_REG_SS_AMP_0V8 + #define RS9_REG_SS_AMP_MASK 0x3 + #define RS9_REG_SS_SSC_100 0 + #define RS9_REG_SS_SSC_M025 (1 << 3) + #define RS9_REG_SS_SSC_M050 (3 << 3) ++#define RS9_REG_SS_SSC_DEFAULT RS9_REG_SS_SSC_100 + #define RS9_REG_SS_SSC_MASK (3 << 3) + #define RS9_REG_SS_SSC_LOCK BIT(5) + #define RS9_REG_SR 0x2 +@@ -205,8 +207,8 @@ static int rs9_get_common_config(struct rs9_driver_data *rs9) + int ret; + + /* Set defaults */ +- rs9->pll_amplitude = RS9_REG_SS_AMP_0V7; +- rs9->pll_ssc = RS9_REG_SS_SSC_100; ++ rs9->pll_amplitude = RS9_REG_SS_AMP_DEFAULT; ++ rs9->pll_ssc = RS9_REG_SS_SSC_DEFAULT; + + /* Output clock amplitude */ + ret = of_property_read_u32(np, "renesas,out-amplitude-microvolt", +@@ -247,13 +249,13 @@ static void rs9_update_config(struct rs9_driver_data *rs9) + int i; + + /* If amplitude is non-default, update it. */ +- if (rs9->pll_amplitude != RS9_REG_SS_AMP_0V7) { ++ if (rs9->pll_amplitude != RS9_REG_SS_AMP_DEFAULT) { + regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_AMP_MASK, + rs9->pll_amplitude); + } + + /* If SSC is non-default, update it. */ +- if (rs9->pll_ssc != RS9_REG_SS_SSC_100) { ++ if (rs9->pll_ssc != RS9_REG_SS_SSC_DEFAULT) { + regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_SSC_MASK, + rs9->pll_ssc); + } +diff --git a/drivers/clk/mediatek/clk-mt8365-mm.c b/drivers/clk/mediatek/clk-mt8365-mm.c +index 01a2ef8f594ef..3f62ec7507336 100644 +--- a/drivers/clk/mediatek/clk-mt8365-mm.c ++++ b/drivers/clk/mediatek/clk-mt8365-mm.c +@@ -53,7 +53,7 @@ static const struct mtk_gate mm_clks[] = { + GATE_MM0(CLK_MM_MM_DSI0, "mm_dsi0", "mm_sel", 17), + GATE_MM0(CLK_MM_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 18), + GATE_MM0(CLK_MM_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 19), +- GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "vpll_dpix", 20), ++ GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "dpi0_sel", 20), + GATE_MM0(CLK_MM_MM_FAKE, "mm_fake", "mm_sel", 21), + GATE_MM0(CLK_MM_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 22), + GATE_MM0(CLK_MM_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 23), +diff --git a/drivers/clk/mediatek/clk-pllfh.c b/drivers/clk/mediatek/clk-pllfh.c +index 3a2b3f90be25d..094ec8a26d668 100644 +--- a/drivers/clk/mediatek/clk-pllfh.c ++++ b/drivers/clk/mediatek/clk-pllfh.c +@@ -68,7 +68,7 @@ void fhctl_parse_dt(const u8 *compatible_node, struct mtk_pllfh_data *pllfhs, + + node = of_find_compatible_node(NULL, NULL, compatible_node); + if (!node) { +- pr_err("cannot find \"%s\"\n", compatible_node); ++ pr_warn("cannot find \"%s\"\n", compatible_node); + return; + } + +diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig +index 8ab08e7b5b6c6..1bb51a0588726 100644 +--- a/drivers/clk/qcom/Kconfig ++++ b/drivers/clk/qcom/Kconfig +@@ -474,6 +474,7 @@ config SC_CAMCC_7280 + + config SC_CAMCC_8280XP + tristate "SC8280XP Camera Clock Controller" ++ depends on ARM64 || COMPILE_TEST + select SC_GCC_8280XP + help + Support for the camera clock controller on Qualcomm Technologies, Inc +@@ -1094,6 +1095,7 @@ config SM_GPUCC_8550 + + config SM_GPUCC_8650 + tristate "SM8650 Graphics Clock Controller" ++ depends on ARM64 || COMPILE_TEST + select SM_GCC_8650 + help + Support for the graphics clock controller on SM8650 devices. +diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c +index 678b805f13d45..5e3da5558f4e0 100644 +--- a/drivers/clk/qcom/apss-ipq-pll.c ++++ b/drivers/clk/qcom/apss-ipq-pll.c +@@ -73,8 +73,9 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = { + }, + }; + ++/* 1.008 GHz configuration */ + static const struct alpha_pll_config ipq5018_pll_config = { +- .l = 0x32, ++ .l = 0x2a, + .config_ctl_val = 0x4001075b, + .config_ctl_hi_val = 0x304, + .main_output_mask = BIT(0), +diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c +index 8a412ef47e163..734a73f322b3a 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.c ++++ b/drivers/clk/qcom/clk-alpha-pll.c +@@ -213,7 +213,6 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { + [PLL_OFF_USER_CTL] = 0x18, + [PLL_OFF_USER_CTL_U] = 0x1c, + [PLL_OFF_CONFIG_CTL] = 0x20, +- [PLL_OFF_CONFIG_CTL_U] = 0xff, + [PLL_OFF_TEST_CTL] = 0x30, + [PLL_OFF_TEST_CTL_U] = 0x34, + [PLL_OFF_STATUS] = 0x28, +diff --git a/drivers/clk/qcom/dispcc-sm6350.c b/drivers/clk/qcom/dispcc-sm6350.c +index 839435362010e..e4b7464c4d0e9 100644 +--- a/drivers/clk/qcom/dispcc-sm6350.c ++++ b/drivers/clk/qcom/dispcc-sm6350.c +@@ -221,26 +221,17 @@ static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = { + }, + }; + +-static const struct freq_tbl ftbl_disp_cc_mdss_dp_link_clk_src[] = { +- F(162000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(270000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(540000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(810000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), +- { } +-}; +- + static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = { + .cmd_rcgr = 0x10f8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, +- .freq_tbl = ftbl_disp_cc_mdss_dp_link_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_link_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +diff --git a/drivers/clk/qcom/dispcc-sm8450.c b/drivers/clk/qcom/dispcc-sm8450.c +index 92e9c4e7b13dc..49bb4f58c3915 100644 +--- a/drivers/clk/qcom/dispcc-sm8450.c ++++ b/drivers/clk/qcom/dispcc-sm8450.c +@@ -309,26 +309,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = { + }, + }; + +-static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = { +- F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- { } +-}; +- + static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = { + .cmd_rcgr = 0x819c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx0_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -382,13 +373,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx1_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -442,13 +432,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx2_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -502,13 +491,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx3_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +diff --git a/drivers/clk/qcom/dispcc-sm8550.c b/drivers/clk/qcom/dispcc-sm8550.c +index 3672c73ac11c6..38ecea805503d 100644 +--- a/drivers/clk/qcom/dispcc-sm8550.c ++++ b/drivers/clk/qcom/dispcc-sm8550.c +@@ -345,26 +345,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = { + }, + }; + +-static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = { +- F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- { } +-}; +- + static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = { + .cmd_rcgr = 0x8170, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_7, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx0_link_clk_src", + .parent_data = disp_cc_parent_data_7, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -418,13 +409,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx1_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -478,13 +468,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx2_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -538,13 +527,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dptx3_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +diff --git a/drivers/clk/qcom/dispcc-sm8650.c b/drivers/clk/qcom/dispcc-sm8650.c +index 9539db0d91145..3eb64bcad487e 100644 +--- a/drivers/clk/qcom/dispcc-sm8650.c ++++ b/drivers/clk/qcom/dispcc-sm8650.c +@@ -343,26 +343,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = { + }, + }; + +-static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = { +- F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), +- { } +-}; +- + static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = { + .cmd_rcgr = 0x8170, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_7, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_dptx0_link_clk_src", + .parent_data = disp_cc_parent_data_7, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -416,13 +407,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_dptx1_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -476,13 +466,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_dptx2_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +@@ -536,13 +525,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = { + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, +- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "disp_cc_mdss_dptx3_link_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, +- .ops = &clk_rcg2_ops, ++ .ops = &clk_byte2_ops, + }, + }; + +diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c +index 1180e48c687ac..275fb3b71ede4 100644 +--- a/drivers/clk/qcom/mmcc-msm8998.c ++++ b/drivers/clk/qcom/mmcc-msm8998.c +@@ -2535,6 +2535,8 @@ static struct clk_branch vmem_ahb_clk = { + + static struct gdsc video_top_gdsc = { + .gdscr = 0x1024, ++ .cxcs = (unsigned int []){ 0x1028, 0x1034, 0x1038 }, ++ .cxc_count = 3, + .pd = { + .name = "video_top", + }, +@@ -2543,20 +2545,26 @@ static struct gdsc video_top_gdsc = { + + static struct gdsc video_subcore0_gdsc = { + .gdscr = 0x1040, ++ .cxcs = (unsigned int []){ 0x1048 }, ++ .cxc_count = 1, + .pd = { + .name = "video_subcore0", + }, + .parent = &video_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, ++ .flags = HW_CTRL, + }; + + static struct gdsc video_subcore1_gdsc = { + .gdscr = 0x1044, ++ .cxcs = (unsigned int []){ 0x104c }, ++ .cxc_count = 1, + .pd = { + .name = "video_subcore1", + }, + .parent = &video_top_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, ++ .flags = HW_CTRL, + }; + + static struct gdsc mdss_gdsc = { +diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c +index 4c2872f45387f..ff3f85e906fe1 100644 +--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c +@@ -139,7 +139,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { + DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2), + DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2), + DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2), +- DEF_MOD("canfd0", 328, R8A779A0_CLK_CANFD), ++ DEF_MOD("canfd0", 328, R8A779A0_CLK_S3D2), + DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0), + DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), + DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), +diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c +index 33532673d25d7..26b71547fdbe3 100644 +--- a/drivers/clk/renesas/r9a07g043-cpg.c ++++ b/drivers/clk/renesas/r9a07g043-cpg.c +@@ -280,6 +280,10 @@ static struct rzg2l_mod_clk r9a07g043_mod_clks[] = { + 0x5a8, 1), + DEF_MOD("tsu_pclk", R9A07G043_TSU_PCLK, R9A07G043_CLK_TSU, + 0x5ac, 0), ++#ifdef CONFIG_RISCV ++ DEF_MOD("nceplic_aclk", R9A07G043_NCEPLIC_ACLK, R9A07G043_CLK_P1, ++ 0x608, 0), ++#endif + }; + + static struct rzg2l_reset r9a07g043_resets[] = { +@@ -338,6 +342,10 @@ static struct rzg2l_reset r9a07g043_resets[] = { + DEF_RST(R9A07G043_ADC_PRESETN, 0x8a8, 0), + DEF_RST(R9A07G043_ADC_ADRST_N, 0x8a8, 1), + DEF_RST(R9A07G043_TSU_PRESETN, 0x8ac, 0), ++#ifdef CONFIG_RISCV ++ DEF_RST(R9A07G043_NCEPLIC_ARESETN, 0x908, 0), ++#endif ++ + }; + + static const unsigned int r9a07g043_crit_mod_clks[] __initconst = { +@@ -347,6 +355,7 @@ static const unsigned int r9a07g043_crit_mod_clks[] __initconst = { + #endif + #ifdef CONFIG_RISCV + MOD_CLK_BASE + R9A07G043_IAX45_CLK, ++ MOD_CLK_BASE + R9A07G043_NCEPLIC_ACLK, + #endif + MOD_CLK_BASE + R9A07G043_DMAC_ACLK, + }; +diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c +index e9c06eb93e666..f04bacacab2cb 100644 +--- a/drivers/clk/samsung/clk-exynosautov9.c ++++ b/drivers/clk/samsung/clk-exynosautov9.c +@@ -352,13 +352,13 @@ static const struct samsung_pll_clock top_pll_clks[] __initconst = { + /* CMU_TOP_PURECLKCOMP */ + PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0, NULL), +- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared1_pll", "oscclk", ++ PLL(pll_0822x, FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1, NULL), +- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared2_pll", "oscclk", ++ PLL(pll_0822x, FOUT_SHARED2_PLL, "fout_shared2_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED2, PLL_CON3_PLL_SHARED2, NULL), +- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared3_pll", "oscclk", ++ PLL(pll_0822x, FOUT_SHARED3_PLL, "fout_shared3_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED3, PLL_CON3_PLL_SHARED3, NULL), +- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared4_pll", "oscclk", ++ PLL(pll_0822x, FOUT_SHARED4_PLL, "fout_shared4_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED4, PLL_CON3_PLL_SHARED4, NULL), + }; + +diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c +index d065e343a85dd..bd3c1b02715b5 100644 +--- a/drivers/clk/samsung/clk-gs101.c ++++ b/drivers/clk/samsung/clk-gs101.c +@@ -2763,33 +2763,33 @@ static const struct samsung_mux_clock peric0_mux_clks[] __initconst = { + MUX(CLK_MOUT_PERIC0_USI0_UART_USER, + "mout_peric0_usi0_uart_user", mout_peric0_usi0_uart_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI0_UART_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI14_USI_USER, +- "mout_peric0_usi14_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI14_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI1_USI_USER, +- "mout_peric0_usi1_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI1_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI2_USI_USER, +- "mout_peric0_usi2_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI2_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI3_USI_USER, +- "mout_peric0_usi3_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI3_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI4_USI_USER, +- "mout_peric0_usi4_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI4_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI5_USI_USER, +- "mout_peric0_usi5_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI5_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI6_USI_USER, +- "mout_peric0_usi6_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI6_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI7_USI_USER, +- "mout_peric0_usi7_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI7_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC0_USI8_USI_USER, +- "mout_peric0_usi8_usi_user", mout_peric0_usi_usi_user_p, +- PLL_CON0_MUX_CLKCMU_PERIC0_USI8_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI14_USI_USER, ++ "mout_peric0_usi14_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI14_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI1_USI_USER, ++ "mout_peric0_usi1_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI1_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI2_USI_USER, ++ "mout_peric0_usi2_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI2_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI3_USI_USER, ++ "mout_peric0_usi3_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI3_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI4_USI_USER, ++ "mout_peric0_usi4_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI4_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI5_USI_USER, ++ "mout_peric0_usi5_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI5_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI6_USI_USER, ++ "mout_peric0_usi6_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI6_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI7_USI_USER, ++ "mout_peric0_usi7_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI7_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC0_USI8_USI_USER, ++ "mout_peric0_usi8_usi_user", mout_peric0_usi_usi_user_p, ++ PLL_CON0_MUX_CLKCMU_PERIC0_USI8_USI_USER, 4, 1), + }; + + static const struct samsung_div_clock peric0_div_clks[] __initconst = { +@@ -2798,33 +2798,42 @@ static const struct samsung_div_clock peric0_div_clks[] __initconst = { + DIV(CLK_DOUT_PERIC0_USI0_UART, + "dout_peric0_usi0_uart", "mout_peric0_usi0_uart_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI0_UART, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI14_USI, +- "dout_peric0_usi14_usi", "mout_peric0_usi14_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI14_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI1_USI, +- "dout_peric0_usi1_usi", "mout_peric0_usi1_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI1_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI2_USI, +- "dout_peric0_usi2_usi", "mout_peric0_usi2_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI2_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI3_USI, +- "dout_peric0_usi3_usi", "mout_peric0_usi3_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI3_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI4_USI, +- "dout_peric0_usi4_usi", "mout_peric0_usi4_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI5_USI, +- "dout_peric0_usi5_usi", "mout_peric0_usi5_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI6_USI, +- "dout_peric0_usi6_usi", "mout_peric0_usi6_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI7_USI, +- "dout_peric0_usi7_usi", "mout_peric0_usi7_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI, 0, 4), +- DIV(CLK_DOUT_PERIC0_USI8_USI, +- "dout_peric0_usi8_usi", "mout_peric0_usi8_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI, 0, 4), ++ DIV_F(CLK_DOUT_PERIC0_USI14_USI, ++ "dout_peric0_usi14_usi", "mout_peric0_usi14_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI14_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI1_USI, ++ "dout_peric0_usi1_usi", "mout_peric0_usi1_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI1_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI2_USI, ++ "dout_peric0_usi2_usi", "mout_peric0_usi2_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI2_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI3_USI, ++ "dout_peric0_usi3_usi", "mout_peric0_usi3_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI3_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI4_USI, ++ "dout_peric0_usi4_usi", "mout_peric0_usi4_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI5_USI, ++ "dout_peric0_usi5_usi", "mout_peric0_usi5_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI6_USI, ++ "dout_peric0_usi6_usi", "mout_peric0_usi6_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI7_USI, ++ "dout_peric0_usi7_usi", "mout_peric0_usi7_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC0_USI8_USI, ++ "dout_peric0_usi8_usi", "mout_peric0_usi8_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), + }; + + static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { +@@ -2857,11 +2866,11 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_0, + "gout_peric0_peric0_top0_ipclk_0", "dout_peric0_usi1_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_0, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_1, + "gout_peric0_peric0_top0_ipclk_1", "dout_peric0_usi2_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_1, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_10, + "gout_peric0_peric0_top0_ipclk_10", "dout_peric0_i3c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_10, +@@ -2889,27 +2898,27 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_2, + "gout_peric0_peric0_top0_ipclk_2", "dout_peric0_usi3_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_2, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_3, + "gout_peric0_peric0_top0_ipclk_3", "dout_peric0_usi4_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_3, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_4, + "gout_peric0_peric0_top0_ipclk_4", "dout_peric0_usi5_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_4, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_5, + "gout_peric0_peric0_top0_ipclk_5", "dout_peric0_usi6_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_5, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_6, + "gout_peric0_peric0_top0_ipclk_6", "dout_peric0_usi7_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_6, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_7, + "gout_peric0_peric0_top0_ipclk_7", "dout_peric0_usi8_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_7, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_8, + "gout_peric0_peric0_top0_ipclk_8", "dout_peric0_i3c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_8, +@@ -2990,7 +2999,7 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { + GATE(CLK_GOUT_PERIC0_PERIC0_TOP1_IPCLK_2, + "gout_peric0_peric0_top1_ipclk_2", "dout_peric0_usi14_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP1_IPCLKPORT_IPCLK_2, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + /* Disabling this clock makes the system hang. Mark the clock as critical. */ + GATE(CLK_GOUT_PERIC0_PERIC0_TOP1_PCLK_0, + "gout_peric0_peric0_top1_pclk_0", "mout_peric0_bus_user", +@@ -3230,47 +3239,53 @@ static const struct samsung_mux_clock peric1_mux_clks[] __initconst = { + MUX(CLK_MOUT_PERIC1_I3C_USER, + "mout_peric1_i3c_user", mout_peric1_nonbususer_p, + PLL_CON0_MUX_CLKCMU_PERIC1_I3C_USER, 4, 1), +- MUX(CLK_MOUT_PERIC1_USI0_USI_USER, +- "mout_peric1_usi0_usi_user", mout_peric1_nonbususer_p, +- PLL_CON0_MUX_CLKCMU_PERIC1_USI0_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC1_USI10_USI_USER, +- "mout_peric1_usi10_usi_user", mout_peric1_nonbususer_p, +- PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC1_USI11_USI_USER, +- "mout_peric1_usi11_usi_user", mout_peric1_nonbususer_p, +- PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC1_USI12_USI_USER, +- "mout_peric1_usi12_usi_user", mout_peric1_nonbususer_p, +- PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC1_USI13_USI_USER, +- "mout_peric1_usi13_usi_user", mout_peric1_nonbususer_p, +- PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USI_USER, 4, 1), +- MUX(CLK_MOUT_PERIC1_USI9_USI_USER, +- "mout_peric1_usi9_usi_user", mout_peric1_nonbususer_p, +- PLL_CON0_MUX_CLKCMU_PERIC1_USI9_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC1_USI0_USI_USER, ++ "mout_peric1_usi0_usi_user", mout_peric1_nonbususer_p, ++ PLL_CON0_MUX_CLKCMU_PERIC1_USI0_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC1_USI10_USI_USER, ++ "mout_peric1_usi10_usi_user", mout_peric1_nonbususer_p, ++ PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC1_USI11_USI_USER, ++ "mout_peric1_usi11_usi_user", mout_peric1_nonbususer_p, ++ PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC1_USI12_USI_USER, ++ "mout_peric1_usi12_usi_user", mout_peric1_nonbususer_p, ++ PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC1_USI13_USI_USER, ++ "mout_peric1_usi13_usi_user", mout_peric1_nonbususer_p, ++ PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USI_USER, 4, 1), ++ nMUX(CLK_MOUT_PERIC1_USI9_USI_USER, ++ "mout_peric1_usi9_usi_user", mout_peric1_nonbususer_p, ++ PLL_CON0_MUX_CLKCMU_PERIC1_USI9_USI_USER, 4, 1), + }; + + static const struct samsung_div_clock peric1_div_clks[] __initconst = { + DIV(CLK_DOUT_PERIC1_I3C, "dout_peric1_i3c", "mout_peric1_i3c_user", + CLK_CON_DIV_DIV_CLK_PERIC1_I3C, 0, 4), +- DIV(CLK_DOUT_PERIC1_USI0_USI, +- "dout_peric1_usi0_usi", "mout_peric1_usi0_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC1_USI0_USI, 0, 4), +- DIV(CLK_DOUT_PERIC1_USI10_USI, +- "dout_peric1_usi10_usi", "mout_peric1_usi10_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, 0, 4), +- DIV(CLK_DOUT_PERIC1_USI11_USI, +- "dout_peric1_usi11_usi", "mout_peric1_usi11_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, 0, 4), +- DIV(CLK_DOUT_PERIC1_USI12_USI, +- "dout_peric1_usi12_usi", "mout_peric1_usi12_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI, 0, 4), +- DIV(CLK_DOUT_PERIC1_USI13_USI, +- "dout_peric1_usi13_usi", "mout_peric1_usi13_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI, 0, 4), +- DIV(CLK_DOUT_PERIC1_USI9_USI, +- "dout_peric1_usi9_usi", "mout_peric1_usi9_usi_user", +- CLK_CON_DIV_DIV_CLK_PERIC1_USI9_USI, 0, 4), ++ DIV_F(CLK_DOUT_PERIC1_USI0_USI, ++ "dout_peric1_usi0_usi", "mout_peric1_usi0_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC1_USI0_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC1_USI10_USI, ++ "dout_peric1_usi10_usi", "mout_peric1_usi10_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC1_USI11_USI, ++ "dout_peric1_usi11_usi", "mout_peric1_usi11_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC1_USI12_USI, ++ "dout_peric1_usi12_usi", "mout_peric1_usi12_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC1_USI13_USI, ++ "dout_peric1_usi13_usi", "mout_peric1_usi13_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), ++ DIV_F(CLK_DOUT_PERIC1_USI9_USI, ++ "dout_peric1_usi9_usi", "mout_peric1_usi9_usi_user", ++ CLK_CON_DIV_DIV_CLK_PERIC1_USI9_USI, 0, 4, ++ CLK_SET_RATE_PARENT, 0), + }; + + static const struct samsung_gate_clock peric1_gate_clks[] __initconst = { +@@ -3305,27 +3320,27 @@ static const struct samsung_gate_clock peric1_gate_clks[] __initconst = { + GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_1, + "gout_peric1_peric1_top0_ipclk_1", "dout_peric1_usi0_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_1, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_2, + "gout_peric1_peric1_top0_ipclk_2", "dout_peric1_usi9_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_2, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_3, + "gout_peric1_peric1_top0_ipclk_3", "dout_peric1_usi10_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_3, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_4, + "gout_peric1_peric1_top0_ipclk_4", "dout_peric1_usi11_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_4, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_5, + "gout_peric1_peric1_top0_ipclk_5", "dout_peric1_usi12_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_5, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_6, + "gout_peric1_peric1_top0_ipclk_6", "dout_peric1_usi13_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_6, +- 21, 0, 0), ++ 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_8, + "gout_peric1_peric1_top0_ipclk_8", "dout_peric1_i3c", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_8, +diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h +index a763309e6f129..556167350bff5 100644 +--- a/drivers/clk/samsung/clk.h ++++ b/drivers/clk/samsung/clk.h +@@ -133,7 +133,7 @@ struct samsung_mux_clock { + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ +- .flags = (f) | CLK_SET_RATE_NO_REPARENT, \ ++ .flags = f, \ + .offset = o, \ + .shift = s, \ + .width = w, \ +@@ -141,9 +141,16 @@ struct samsung_mux_clock { + } + + #define MUX(_id, cname, pnames, o, s, w) \ +- __MUX(_id, cname, pnames, o, s, w, 0, 0) ++ __MUX(_id, cname, pnames, o, s, w, CLK_SET_RATE_NO_REPARENT, 0) + + #define MUX_F(_id, cname, pnames, o, s, w, f, mf) \ ++ __MUX(_id, cname, pnames, o, s, w, (f) | CLK_SET_RATE_NO_REPARENT, mf) ++ ++/* Used by MUX clocks where reparenting on clock rate change is allowed. */ ++#define nMUX(_id, cname, pnames, o, s, w) \ ++ __MUX(_id, cname, pnames, o, s, w, 0, 0) ++ ++#define nMUX_F(_id, cname, pnames, o, s, w, f, mf) \ + __MUX(_id, cname, pnames, o, s, w, f, mf) + + /** +diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c +index 1a1857b0a6f48..ea8438550b490 100644 +--- a/drivers/cpufreq/brcmstb-avs-cpufreq.c ++++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c +@@ -481,9 +481,12 @@ static bool brcm_avs_is_firmware_loaded(struct private_data *priv) + static unsigned int brcm_avs_cpufreq_get(unsigned int cpu) + { + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); ++ struct private_data *priv; ++ + if (!policy) + return 0; +- struct private_data *priv = policy->driver_data; ++ ++ priv = policy->driver_data; + + cpufreq_cpu_put(policy); + +diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c +index 64420d9cfd1ed..15f1d41920a33 100644 +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -741,10 +741,15 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) + { + struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); +- struct cppc_cpudata *cpu_data = policy->driver_data; ++ struct cppc_cpudata *cpu_data; + u64 delivered_perf; + int ret; + ++ if (!policy) ++ return -ENODEV; ++ ++ cpu_data = policy->driver_data; ++ + cpufreq_cpu_put(policy); + + ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0); +@@ -822,10 +827,15 @@ static struct cpufreq_driver cppc_cpufreq_driver = { + static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu) + { + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); +- struct cppc_cpudata *cpu_data = policy->driver_data; ++ struct cppc_cpudata *cpu_data; + u64 desired_perf; + int ret; + ++ if (!policy) ++ return -ENODEV; ++ ++ cpu_data = policy->driver_data; ++ + cpufreq_cpu_put(policy); + + ret = cppc_get_desired_perf(cpu, &desired_perf); +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 66e10a19d76ab..fd9c3ed21f49c 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -1679,10 +1679,13 @@ static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy) + */ + if (cpufreq_driver->offline) { + cpufreq_driver->offline(policy); +- } else if (cpufreq_driver->exit) { +- cpufreq_driver->exit(policy); +- policy->freq_table = NULL; ++ return; + } ++ ++ if (cpufreq_driver->exit) ++ cpufreq_driver->exit(policy); ++ ++ policy->freq_table = NULL; + } + + static int cpufreq_offline(unsigned int cpu) +@@ -1740,7 +1743,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) + } + + /* We did light-weight exit earlier, do full tear down now */ +- if (cpufreq_driver->offline) ++ if (cpufreq_driver->offline && cpufreq_driver->exit) + cpufreq_driver->exit(policy); + + up_write(&policy->rwsem); +diff --git a/drivers/crypto/bcm/spu2.c b/drivers/crypto/bcm/spu2.c +index 07989bb8c220a..3fdc64b5a65e7 100644 +--- a/drivers/crypto/bcm/spu2.c ++++ b/drivers/crypto/bcm/spu2.c +@@ -495,7 +495,7 @@ static void spu2_dump_omd(u8 *omd, u16 hash_key_len, u16 ciph_key_len, + if (hash_iv_len) { + packet_log(" Hash IV Length %u bytes\n", hash_iv_len); + packet_dump(" hash IV: ", ptr, hash_iv_len); +- ptr += ciph_key_len; ++ ptr += hash_iv_len; + } + + if (ciph_iv_len) { +diff --git a/drivers/crypto/ccp/sp-platform.c b/drivers/crypto/ccp/sp-platform.c +index 4733012377601..ff6ceb4feee04 100644 +--- a/drivers/crypto/ccp/sp-platform.c ++++ b/drivers/crypto/ccp/sp-platform.c +@@ -39,44 +39,38 @@ static const struct sp_dev_vdata dev_vdata[] = { + }, + }; + +-#ifdef CONFIG_ACPI + static const struct acpi_device_id sp_acpi_match[] = { + { "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] }, + { }, + }; + MODULE_DEVICE_TABLE(acpi, sp_acpi_match); +-#endif + +-#ifdef CONFIG_OF + static const struct of_device_id sp_of_match[] = { + { .compatible = "amd,ccp-seattle-v1a", + .data = (const void *)&dev_vdata[0] }, + { }, + }; + MODULE_DEVICE_TABLE(of, sp_of_match); +-#endif + + static struct sp_dev_vdata *sp_get_of_version(struct platform_device *pdev) + { +-#ifdef CONFIG_OF + const struct of_device_id *match; + + match = of_match_node(sp_of_match, pdev->dev.of_node); + if (match && match->data) + return (struct sp_dev_vdata *)match->data; +-#endif ++ + return NULL; + } + + static struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev) + { +-#ifdef CONFIG_ACPI + const struct acpi_device_id *match; + + match = acpi_match_device(sp_acpi_match, &pdev->dev); + if (match && match->driver_data) + return (struct sp_dev_vdata *)match->driver_data; +-#endif ++ + return NULL; + } + +@@ -212,12 +206,8 @@ static int sp_platform_resume(struct platform_device *pdev) + static struct platform_driver sp_platform_driver = { + .driver = { + .name = "ccp", +-#ifdef CONFIG_ACPI + .acpi_match_table = sp_acpi_match, +-#endif +-#ifdef CONFIG_OF + .of_match_table = sp_of_match, +-#endif + }, + .probe = sp_platform_probe, + .remove_new = sp_platform_remove, +diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c +index 1102c47f8293d..1d0ef47a9f250 100644 +--- a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c ++++ b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c +@@ -296,7 +296,7 @@ static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev) + { + if (adf_gen4_init_thd2arb_map(accel_dev)) + dev_warn(&GET_DEV(accel_dev), +- "Generate of the thread to arbiter map failed"); ++ "Failed to generate thread to arbiter mapping"); + + return GET_HW_DATA(accel_dev)->thd_to_arb_map; + } +diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +index 927506cf271d0..fb34fd7f03952 100644 +--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c ++++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +@@ -208,7 +208,7 @@ static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev) + { + if (adf_gen4_init_thd2arb_map(accel_dev)) + dev_warn(&GET_DEV(accel_dev), +- "Generate of the thread to arbiter map failed"); ++ "Failed to generate thread to arbiter mapping"); + + return GET_HW_DATA(accel_dev)->thd_to_arb_map; + } +diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +index 9762f2bf7727f..d26564cebdec4 100644 +--- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c ++++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +@@ -197,7 +197,9 @@ module_pci_driver(adf_driver); + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_AUTHOR("Intel"); + MODULE_FIRMWARE(ADF_4XXX_FW); ++MODULE_FIRMWARE(ADF_402XX_FW); + MODULE_FIRMWARE(ADF_4XXX_MMP); ++MODULE_FIRMWARE(ADF_402XX_MMP); + MODULE_DESCRIPTION("Intel(R) QuickAssist Technology"); + MODULE_VERSION(ADF_DRV_VERSION); + MODULE_SOFTDEP("pre: crypto-intel_qat"); +diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c +index 7fc7a77f6aed9..c7ad8cf07863b 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c +@@ -149,5 +149,6 @@ void adf_gen4_init_tl_data(struct adf_tl_hw_data *tl_data) + tl_data->sl_exec_counters = sl_exec_counters; + tl_data->rp_counters = rp_counters; + tl_data->num_rp_counters = ARRAY_SIZE(rp_counters); ++ tl_data->max_sl_cnt = ADF_GEN4_TL_MAX_SLICES_PER_TYPE; + } + EXPORT_SYMBOL_GPL(adf_gen4_init_tl_data); +diff --git a/drivers/crypto/intel/qat/qat_common/adf_rl.c b/drivers/crypto/intel/qat/qat_common/adf_rl.c +index d4f2db3c53d8c..e10f0024f4b85 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_rl.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_rl.c +@@ -1125,7 +1125,7 @@ int adf_rl_start(struct adf_accel_dev *accel_dev) + } + + if ((fw_caps & RL_CAPABILITY_MASK) != RL_CAPABILITY_VALUE) { +- dev_info(&GET_DEV(accel_dev), "not supported\n"); ++ dev_info(&GET_DEV(accel_dev), "feature not supported by FW\n"); + ret = -EOPNOTSUPP; + goto ret_free; + } +diff --git a/drivers/crypto/intel/qat/qat_common/adf_telemetry.c b/drivers/crypto/intel/qat/qat_common/adf_telemetry.c +index 2ff714d11bd2f..74fb0c2ed2412 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_telemetry.c ++++ b/drivers/crypto/intel/qat/qat_common/adf_telemetry.c +@@ -41,6 +41,20 @@ static int validate_tl_data(struct adf_tl_hw_data *tl_data) + return 0; + } + ++static int validate_tl_slice_counters(struct icp_qat_fw_init_admin_slice_cnt *slice_count, ++ u8 max_slices_per_type) ++{ ++ u8 *sl_counter = (u8 *)slice_count; ++ int i; ++ ++ for (i = 0; i < ADF_TL_SL_CNT_COUNT; i++) { ++ if (sl_counter[i] > max_slices_per_type) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int adf_tl_alloc_mem(struct adf_accel_dev *accel_dev) + { + struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev); +@@ -214,6 +228,13 @@ int adf_tl_run(struct adf_accel_dev *accel_dev, int state) + return ret; + } + ++ ret = validate_tl_slice_counters(&telemetry->slice_cnt, tl_data->max_sl_cnt); ++ if (ret) { ++ dev_err(dev, "invalid value returned by FW\n"); ++ adf_send_admin_tl_stop(accel_dev); ++ return ret; ++ } ++ + telemetry->hbuffs = state; + atomic_set(&telemetry->state, state); + +diff --git a/drivers/crypto/intel/qat/qat_common/adf_telemetry.h b/drivers/crypto/intel/qat/qat_common/adf_telemetry.h +index 9be81cd3b8860..e54a406cc1b4a 100644 +--- a/drivers/crypto/intel/qat/qat_common/adf_telemetry.h ++++ b/drivers/crypto/intel/qat/qat_common/adf_telemetry.h +@@ -40,6 +40,7 @@ struct adf_tl_hw_data { + u8 num_dev_counters; + u8 num_rp_counters; + u8 max_rp; ++ u8 max_sl_cnt; + }; + + struct adf_telemetry { +diff --git a/drivers/crypto/marvell/octeontx2/cn10k_cpt.c b/drivers/crypto/marvell/octeontx2/cn10k_cpt.c +index 79b4e74804f6d..6bfc59e677478 100644 +--- a/drivers/crypto/marvell/octeontx2/cn10k_cpt.c ++++ b/drivers/crypto/marvell/octeontx2/cn10k_cpt.c +@@ -138,6 +138,10 @@ int cn10k_cpt_hw_ctx_init(struct pci_dev *pdev, + return -ENOMEM; + cptr_dma = dma_map_single(&pdev->dev, hctx, CN10K_CPT_HW_CTX_SIZE, + DMA_BIDIRECTIONAL); ++ if (dma_mapping_error(&pdev->dev, cptr_dma)) { ++ kfree(hctx); ++ return -ENOMEM; ++ } + + cn10k_cpt_hw_ctx_set(hctx, 1); + er_ctx->hw_ctx = hctx; +diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c +index 797e1ebff2997..f24b67c64d5ec 100644 +--- a/drivers/dax/bus.c ++++ b/drivers/dax/bus.c +@@ -192,7 +192,7 @@ static u64 dev_dax_size(struct dev_dax *dev_dax) + u64 size = 0; + int i; + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_dev_rwsem)); ++ lockdep_assert_held(&dax_dev_rwsem); + + for (i = 0; i < dev_dax->nr_range; i++) + size += range_len(&dev_dax->ranges[i].range); +@@ -302,7 +302,7 @@ static unsigned long long dax_region_avail_size(struct dax_region *dax_region) + resource_size_t size = resource_size(&dax_region->res); + struct resource *res; + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_region_rwsem)); ++ lockdep_assert_held(&dax_region_rwsem); + + for_each_dax_region_resource(dax_region, res) + size -= resource_size(res); +@@ -447,7 +447,7 @@ static void trim_dev_dax_range(struct dev_dax *dev_dax) + struct range *range = &dev_dax->ranges[i].range; + struct dax_region *dax_region = dev_dax->region; + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_region_rwsem)); ++ lockdep_assert_held_write(&dax_region_rwsem); + dev_dbg(&dev_dax->dev, "delete range[%d]: %#llx:%#llx\n", i, + (unsigned long long)range->start, + (unsigned long long)range->end); +@@ -465,26 +465,17 @@ static void free_dev_dax_ranges(struct dev_dax *dev_dax) + trim_dev_dax_range(dev_dax); + } + +-static void __unregister_dev_dax(void *dev) ++static void unregister_dev_dax(void *dev) + { + struct dev_dax *dev_dax = to_dev_dax(dev); + + dev_dbg(dev, "%s\n", __func__); + ++ down_write(&dax_region_rwsem); + kill_dev_dax(dev_dax); + device_del(dev); + free_dev_dax_ranges(dev_dax); + put_device(dev); +-} +- +-static void unregister_dev_dax(void *dev) +-{ +- if (rwsem_is_locked(&dax_region_rwsem)) +- return __unregister_dev_dax(dev); +- +- if (WARN_ON_ONCE(down_write_killable(&dax_region_rwsem) != 0)) +- return; +- __unregister_dev_dax(dev); + up_write(&dax_region_rwsem); + } + +@@ -507,7 +498,7 @@ static int __free_dev_dax_id(struct dev_dax *dev_dax) + struct dax_region *dax_region; + int rc = dev_dax->id; + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_dev_rwsem)); ++ lockdep_assert_held_write(&dax_dev_rwsem); + + if (!dev_dax->dyn_id || dev_dax->id < 0) + return -1; +@@ -560,15 +551,10 @@ static ssize_t delete_store(struct device *dev, struct device_attribute *attr, + if (!victim) + return -ENXIO; + +- rc = down_write_killable(&dax_region_rwsem); +- if (rc) +- return rc; +- rc = down_write_killable(&dax_dev_rwsem); +- if (rc) { +- up_write(&dax_region_rwsem); +- return rc; +- } ++ device_lock(dev); ++ device_lock(victim); + dev_dax = to_dev_dax(victim); ++ down_write(&dax_dev_rwsem); + if (victim->driver || dev_dax_size(dev_dax)) + rc = -EBUSY; + else { +@@ -589,11 +575,12 @@ static ssize_t delete_store(struct device *dev, struct device_attribute *attr, + rc = -EBUSY; + } + up_write(&dax_dev_rwsem); ++ device_unlock(victim); + + /* won the race to invalidate the device, clean it up */ + if (do_del) + devm_release_action(dev, unregister_dev_dax, victim); +- up_write(&dax_region_rwsem); ++ device_unlock(dev); + put_device(victim); + + return rc; +@@ -705,7 +692,7 @@ static void dax_mapping_release(struct device *dev) + put_device(parent); + } + +-static void __unregister_dax_mapping(void *data) ++static void unregister_dax_mapping(void *data) + { + struct device *dev = data; + struct dax_mapping *mapping = to_dax_mapping(dev); +@@ -713,25 +700,12 @@ static void __unregister_dax_mapping(void *data) + + dev_dbg(dev, "%s\n", __func__); + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_region_rwsem)); +- + dev_dax->ranges[mapping->range_id].mapping = NULL; + mapping->range_id = -1; + + device_unregister(dev); + } + +-static void unregister_dax_mapping(void *data) +-{ +- if (rwsem_is_locked(&dax_region_rwsem)) +- return __unregister_dax_mapping(data); +- +- if (WARN_ON_ONCE(down_write_killable(&dax_region_rwsem) != 0)) +- return; +- __unregister_dax_mapping(data); +- up_write(&dax_region_rwsem); +-} +- + static struct dev_dax_range *get_dax_range(struct device *dev) + { + struct dax_mapping *mapping = to_dax_mapping(dev); +@@ -830,7 +804,7 @@ static int devm_register_dax_mapping(struct dev_dax *dev_dax, int range_id) + struct device *dev; + int rc; + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_region_rwsem)); ++ lockdep_assert_held_write(&dax_region_rwsem); + + if (dev_WARN_ONCE(&dev_dax->dev, !dax_region->dev->driver, + "region disabled\n")) +@@ -876,7 +850,7 @@ static int alloc_dev_dax_range(struct dev_dax *dev_dax, u64 start, + struct resource *alloc; + int i, rc; + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_region_rwsem)); ++ lockdep_assert_held_write(&dax_region_rwsem); + + /* handle the seed alloc special case */ + if (!size) { +@@ -935,7 +909,7 @@ static int adjust_dev_dax_range(struct dev_dax *dev_dax, struct resource *res, r + struct device *dev = &dev_dax->dev; + int rc; + +- WARN_ON_ONCE(!rwsem_is_locked(&dax_region_rwsem)); ++ lockdep_assert_held_write(&dax_region_rwsem); + + if (dev_WARN_ONCE(dev, !size, "deletion is handled by dev_dax_shrink\n")) + return -EINVAL; +@@ -963,11 +937,11 @@ static ssize_t size_show(struct device *dev, + unsigned long long size; + int rc; + +- rc = down_write_killable(&dax_dev_rwsem); ++ rc = down_read_interruptible(&dax_dev_rwsem); + if (rc) + return rc; + size = dev_dax_size(dev_dax); +- up_write(&dax_dev_rwsem); ++ up_read(&dax_dev_rwsem); + + return sysfs_emit(buf, "%llu\n", size); + } +@@ -1566,12 +1540,8 @@ static struct dev_dax *__devm_create_dev_dax(struct dev_dax_data *data) + struct dev_dax *devm_create_dev_dax(struct dev_dax_data *data) + { + struct dev_dax *dev_dax; +- int rc; +- +- rc = down_write_killable(&dax_region_rwsem); +- if (rc) +- return ERR_PTR(rc); + ++ down_write(&dax_region_rwsem); + dev_dax = __devm_create_dev_dax(data); + up_write(&dax_region_rwsem); + +diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c +index d0f6693ca1426..32019dc33cca7 100644 +--- a/drivers/dpll/dpll_core.c ++++ b/drivers/dpll/dpll_core.c +@@ -449,7 +449,7 @@ static int dpll_pin_prop_dup(const struct dpll_pin_properties *src, + sizeof(*src->freq_supported); + dst->freq_supported = kmemdup(src->freq_supported, + freq_size, GFP_KERNEL); +- if (!src->freq_supported) ++ if (!dst->freq_supported) + return -ENOMEM; + } + if (src->board_label) { +diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c +index 9c5b6f8bd8bd5..27996b7924c82 100644 +--- a/drivers/edac/skx_common.c ++++ b/drivers/edac/skx_common.c +@@ -648,7 +648,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val, + memset(&res, 0, sizeof(res)); + res.mce = mce; + res.addr = mce->addr & MCI_ADDR_PHYSADDR; +- if (!pfn_to_online_page(res.addr >> PAGE_SHIFT)) { ++ if (!pfn_to_online_page(res.addr >> PAGE_SHIFT) && !arch_is_platform_page(res.addr)) { + pr_err("Invalid address 0x%llx in IA32_MC%d_ADDR\n", mce->addr, mce->bank); + return NOTIFY_DONE; + } +diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c +index 90283f160a228..29c24578ad2bf 100644 +--- a/drivers/firmware/qcom/qcom_scm.c ++++ b/drivers/firmware/qcom/qcom_scm.c +@@ -1624,7 +1624,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send); + * We do not yet support re-entrant calls via the qseecom interface. To prevent + + any potential issues with this, only allow validated machines for now. + */ +-static const struct of_device_id qcom_scm_qseecom_allowlist[] = { ++static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = { + { .compatible = "lenovo,thinkpad-x13s", }, + { } + }; +@@ -1713,7 +1713,7 @@ static int qcom_scm_qseecom_init(struct qcom_scm *scm) + */ + bool qcom_scm_is_available(void) + { +- return !!__scm; ++ return !!READ_ONCE(__scm); + } + EXPORT_SYMBOL_GPL(qcom_scm_is_available); + +@@ -1794,10 +1794,12 @@ static int qcom_scm_probe(struct platform_device *pdev) + if (!scm) + return -ENOMEM; + ++ scm->dev = &pdev->dev; + ret = qcom_scm_find_dload_address(&pdev->dev, &scm->dload_mode_addr); + if (ret < 0) + return ret; + ++ init_completion(&scm->waitq_comp); + mutex_init(&scm->scm_bw_lock); + + scm->path = devm_of_icc_get(&pdev->dev, NULL); +@@ -1829,10 +1831,8 @@ static int qcom_scm_probe(struct platform_device *pdev) + if (ret) + return ret; + +- __scm = scm; +- __scm->dev = &pdev->dev; +- +- init_completion(&__scm->waitq_comp); ++ /* Let all above stores be available after this */ ++ smp_store_release(&__scm, scm); + + irq = platform_get_irq_optional(pdev, 0); + if (irq < 0) { +diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c +index 322aada20f742..ac34876a97f8b 100644 +--- a/drivers/firmware/raspberrypi.c ++++ b/drivers/firmware/raspberrypi.c +@@ -9,6 +9,7 @@ + #include <linux/dma-mapping.h> + #include <linux/kref.h> + #include <linux/mailbox_client.h> ++#include <linux/mailbox_controller.h> + #include <linux/module.h> + #include <linux/of.h> + #include <linux/of_platform.h> +@@ -97,8 +98,8 @@ int rpi_firmware_property_list(struct rpi_firmware *fw, + if (size & 3) + return -EINVAL; + +- buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr, +- GFP_ATOMIC); ++ buf = dma_alloc_coherent(fw->chan->mbox->dev, PAGE_ALIGN(size), ++ &bus_addr, GFP_ATOMIC); + if (!buf) + return -ENOMEM; + +@@ -126,7 +127,7 @@ int rpi_firmware_property_list(struct rpi_firmware *fw, + ret = -EINVAL; + } + +- dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr); ++ dma_free_coherent(fw->chan->mbox->dev, PAGE_ALIGN(size), buf, bus_addr); + + return ret; + } +diff --git a/drivers/gpio/gpio-npcm-sgpio.c b/drivers/gpio/gpio-npcm-sgpio.c +index d31788b43abcc..2605706145434 100644 +--- a/drivers/gpio/gpio-npcm-sgpio.c ++++ b/drivers/gpio/gpio-npcm-sgpio.c +@@ -434,7 +434,7 @@ static void npcm_sgpio_irq_handler(struct irq_desc *desc) + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct irq_chip *ic = irq_desc_get_chip(desc); + struct npcm_sgpio *gpio = gpiochip_get_data(gc); +- unsigned int i, j, girq; ++ unsigned int i, j; + unsigned long reg; + + chained_irq_enter(ic, desc); +@@ -443,11 +443,9 @@ static void npcm_sgpio_irq_handler(struct irq_desc *desc) + const struct npcm_sgpio_bank *bank = &npcm_sgpio_banks[i]; + + reg = ioread8(bank_reg(gpio, bank, EVENT_STS)); +- for_each_set_bit(j, ®, 8) { +- girq = irq_find_mapping(gc->irq.domain, +- i * 8 + gpio->nout_sgpio + j); +- generic_handle_domain_irq(gc->irq.domain, girq); +- } ++ for_each_set_bit(j, ®, 8) ++ generic_handle_domain_irq(gc->irq.domain, ++ i * 8 + gpio->nout_sgpio + j); + } + + chained_irq_exit(ic, desc); +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 b7e57aa273619..b0d192c6e63eb 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 +@@ -402,6 +402,11 @@ bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx, + i += increment) { + if (j == hw_points - 1) + break; ++ if (i >= TRANSFER_FUNC_POINTS) { ++ DC_LOG_ERROR("Index out of bounds: i=%d, TRANSFER_FUNC_POINTS=%d\n", ++ i, TRANSFER_FUNC_POINTS); ++ return false; ++ } + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +index 9067ca78f8511..a14f99f4f14a5 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +@@ -999,8 +999,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, + if (pipe_ctx->plane_res.dpp) + update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false; + +- if ((pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) && +- pipe_ctx->plane_res.mpcc_inst >= 0) ++ if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) + update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false; + + if (pipe_ctx->stream_res.dsc) +diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c +index 626709bec6f5f..2577f0cef8fcd 100644 +--- a/drivers/gpu/drm/arm/malidp_mw.c ++++ b/drivers/gpu/drm/arm/malidp_mw.c +@@ -72,7 +72,10 @@ static void malidp_mw_connector_reset(struct drm_connector *connector) + __drm_atomic_helper_connector_destroy_state(connector->state); + + kfree(connector->state); +- __drm_atomic_helper_connector_reset(connector, &mw_state->base); ++ connector->state = NULL; ++ ++ if (mw_state) ++ __drm_atomic_helper_connector_reset(connector, &mw_state->base); + } + + static enum drm_connector_status +diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c +index 9d96d28d6fe8e..59e9ad3499696 100644 +--- a/drivers/gpu/drm/bridge/analogix/anx7625.c ++++ b/drivers/gpu/drm/bridge/analogix/anx7625.c +@@ -2066,10 +2066,8 @@ static int anx7625_setup_dsi_device(struct anx7625_data *ctx) + }; + + host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node); +- if (!host) { +- DRM_DEV_ERROR(dev, "fail to find dsi host.\n"); +- return -EPROBE_DEFER; +- } ++ if (!host) ++ return dev_err_probe(dev, -EPROBE_DEFER, "fail to find dsi host.\n"); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) { +@@ -2471,15 +2469,22 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge, + mutex_unlock(&ctx->aux_lock); + } + ++static void ++anx7625_audio_update_connector_status(struct anx7625_data *ctx, ++ enum drm_connector_status status); ++ + static enum drm_connector_status + anx7625_bridge_detect(struct drm_bridge *bridge) + { + struct anx7625_data *ctx = bridge_to_anx7625(bridge); + struct device *dev = ctx->dev; ++ enum drm_connector_status status; + + DRM_DEV_DEBUG_DRIVER(dev, "drm bridge detect\n"); + +- return anx7625_sink_detect(ctx); ++ status = anx7625_sink_detect(ctx); ++ anx7625_audio_update_connector_status(ctx, status); ++ return status; + } + + static const struct drm_edid *anx7625_bridge_edid_read(struct drm_bridge *bridge, +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +index e226acc5c15e1..8a91ef0ae0651 100644 +--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +@@ -2059,6 +2059,9 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge, + mhdp_state = to_cdns_mhdp_bridge_state(new_state); + + mhdp_state->current_mode = drm_mode_duplicate(bridge->dev, mode); ++ if (!mhdp_state->current_mode) ++ return; ++ + drm_mode_set_name(mhdp_state->current_mode); + + dev_dbg(mhdp->dev, "%s: Enabling mode %s\n", __func__, mode->name); +diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c +index 82d23e4df09eb..ff3284b6b1a37 100644 +--- a/drivers/gpu/drm/bridge/chipone-icn6211.c ++++ b/drivers/gpu/drm/bridge/chipone-icn6211.c +@@ -563,10 +563,8 @@ static int chipone_dsi_host_attach(struct chipone *icn) + + host = of_find_mipi_dsi_host_by_node(host_node); + of_node_put(host_node); +- if (!host) { +- dev_err(dev, "failed to find dsi host\n"); +- return -EPROBE_DEFER; +- } ++ if (!host) ++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); + + dsi = mipi_dsi_device_register_full(host, &info); + if (IS_ERR(dsi)) { +diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c +index 4b2ae27f0a57f..1a9defa15663c 100644 +--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c ++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c +@@ -494,10 +494,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt) + }; + + host = of_find_mipi_dsi_host_by_node(lt->host_node); +- if (!host) { +- dev_err(dev, "failed to find dsi host\n"); +- return -EPROBE_DEFER; +- } ++ if (!host) ++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) { +diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c +index a9c7e2b07ea10..b99fe87ec7389 100644 +--- a/drivers/gpu/drm/bridge/lontium-lt9611.c ++++ b/drivers/gpu/drm/bridge/lontium-lt9611.c +@@ -761,10 +761,8 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611, + int ret; + + host = of_find_mipi_dsi_host_by_node(dsi_node); +- if (!host) { +- dev_err(lt9611->dev, "failed to find dsi host\n"); +- return ERR_PTR(-EPROBE_DEFER); +- } ++ if (!host) ++ return ERR_PTR(dev_err_probe(lt9611->dev, -EPROBE_DEFER, "failed to find dsi host\n")); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) { +diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +index f4f593ad8f795..ab702471f3ab1 100644 +--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c ++++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +@@ -266,10 +266,8 @@ static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc, + int ret; + + host = of_find_mipi_dsi_host_by_node(dsi_node); +- if (!host) { +- dev_err(dev, "failed to find dsi host\n"); +- return ERR_PTR(-EPROBE_DEFER); +- } ++ if (!host) ++ return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n")); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) { +diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c +index 90a89d70d8328..fea4f00a20f83 100644 +--- a/drivers/gpu/drm/bridge/tc358775.c ++++ b/drivers/gpu/drm/bridge/tc358775.c +@@ -610,10 +610,8 @@ static int tc_attach_host(struct tc_data *tc) + }; + + host = of_find_mipi_dsi_host_by_node(tc->host_node); +- if (!host) { +- dev_err(dev, "failed to find dsi host\n"); +- return -EPROBE_DEFER; +- } ++ if (!host) ++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); + + dsi = devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) { +diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c +index ca3348109bcd2..6b559e0713012 100644 +--- a/drivers/gpu/drm/bridge/ti-dlpc3433.c ++++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c +@@ -319,12 +319,11 @@ static int dlpc_host_attach(struct dlpc *dlpc) + .channel = 0, + .node = NULL, + }; ++ int ret; + + host = of_find_mipi_dsi_host_by_node(dlpc->host_node); +- if (!host) { +- DRM_DEV_ERROR(dev, "failed to find dsi host\n"); +- return -EPROBE_DEFER; +- } ++ if (!host) ++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); + + dlpc->dsi = mipi_dsi_device_register_full(host, &info); + if (IS_ERR(dlpc->dsi)) { +@@ -336,7 +335,11 @@ static int dlpc_host_attach(struct dlpc *dlpc) + dlpc->dsi->format = MIPI_DSI_FMT_RGB565; + dlpc->dsi->lanes = dlpc->dsi_lanes; + +- return devm_mipi_dsi_attach(dev, dlpc->dsi); ++ ret = devm_mipi_dsi_attach(dev, dlpc->dsi); ++ if (ret) ++ DRM_DEV_ERROR(dev, "failed to attach dsi host\n"); ++ ++ return ret; + } + + static int dlpc3433_probe(struct i2c_client *client) +@@ -367,10 +370,8 @@ static int dlpc3433_probe(struct i2c_client *client) + drm_bridge_add(&dlpc->bridge); + + ret = dlpc_host_attach(dlpc); +- if (ret) { +- DRM_DEV_ERROR(dev, "failed to attach dsi host\n"); ++ if (ret) + goto err_remove_bridge; +- } + + return 0; + +diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml +index 0857773e5c5fd..8bc63912fddb4 100644 +--- a/drivers/gpu/drm/ci/test.yml ++++ b/drivers/gpu/drm/ci/test.yml +@@ -252,11 +252,11 @@ i915:cml: + i915:tgl: + extends: + - .i915 +- parallel: 8 ++ parallel: 5 + variables: +- DEVICE_TYPE: asus-cx9400-volteer ++ DEVICE_TYPE: acer-cp514-2h-1130g7-volteer + GPU_VERSION: tgl +- RUNNER_TAG: mesa-ci-x86-64-lava-asus-cx9400-volteer ++ RUNNER_TAG: mesa-ci-x86-64-lava-acer-cp514-2h-1130g7-volteer + + .amdgpu: + extends: +diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c +index 521a71c61b164..17ed94885dc3b 100644 +--- a/drivers/gpu/drm/drm_bridge.c ++++ b/drivers/gpu/drm/drm_bridge.c +@@ -687,11 +687,17 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, + */ + list_for_each_entry_from(next, &encoder->bridge_chain, + chain_node) { +- if (next->pre_enable_prev_first) { ++ if (!next->pre_enable_prev_first) { + next = list_prev_entry(next, chain_node); + limit = next; + break; + } ++ ++ if (list_is_last(&next->chain_node, ++ &encoder->bridge_chain)) { ++ limit = next; ++ break; ++ } + } + + /* Call these bridges in reverse order */ +@@ -774,7 +780,7 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, + /* Found first bridge that does NOT + * request prev to be enabled first + */ +- limit = list_prev_entry(next, chain_node); ++ limit = next; + break; + } + } +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index 923c4423151c1..9064cdeb1319b 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -7324,7 +7324,7 @@ static void drm_parse_tiled_block(struct drm_connector *connector, + static bool displayid_is_tiled_block(const struct displayid_iter *iter, + const struct displayid_block *block) + { +- return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 && ++ return (displayid_version(iter) < DISPLAY_ID_STRUCTURE_VER_20 && + block->tag == DATA_BLOCK_TILED_DISPLAY) || + (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 && + block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY); +diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c +index ef6e416522f8a..9874ff6d47181 100644 +--- a/drivers/gpu/drm/drm_mipi_dsi.c ++++ b/drivers/gpu/drm/drm_mipi_dsi.c +@@ -654,7 +654,7 @@ EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size); + * + * Return: 0 on success or a negative error code on failure. + */ +-ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable) ++int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable) + { + /* Note: Needs updating for non-default PPS or algorithm */ + u8 tx[2] = { enable << 0, 0 }; +@@ -679,8 +679,8 @@ EXPORT_SYMBOL(mipi_dsi_compression_mode); + * + * Return: 0 on success or a negative error code on failure. + */ +-ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, +- const struct drm_dsc_picture_parameter_set *pps) ++int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, ++ const struct drm_dsc_picture_parameter_set *pps) + { + struct mipi_dsi_msg msg = { + .channel = dsi->channel, +diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c +index b7fef3c797e6c..4f99b4af871c0 100644 +--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c ++++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c +@@ -46,7 +46,7 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev) + if (!mips_data) + return -ENOMEM; + +- for (page_nr = 0; page_nr < ARRAY_SIZE(mips_data->pt_pages); page_nr++) { ++ for (page_nr = 0; page_nr < PVR_MIPS_PT_PAGE_COUNT; page_nr++) { + mips_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!mips_data->pt_pages[page_nr]) { + err = -ENOMEM; +@@ -102,7 +102,7 @@ pvr_vm_mips_fini(struct pvr_device *pvr_dev) + int page_nr; + + vunmap(mips_data->pt); +- for (page_nr = ARRAY_SIZE(mips_data->pt_pages) - 1; page_nr >= 0; page_nr--) { ++ for (page_nr = PVR_MIPS_PT_PAGE_COUNT - 1; page_nr >= 0; page_nr--) { + dma_unmap_page(from_pvr_device(pvr_dev)->dev, + mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE); + +diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +index a04499c4f9ca2..29207b2756c14 100644 +--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +@@ -1009,10 +1009,10 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, + + mtk_crtc->mmsys_dev = priv->mmsys_dev; + mtk_crtc->ddp_comp_nr = path_len; +- mtk_crtc->ddp_comp = devm_kmalloc_array(dev, +- mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0), +- sizeof(*mtk_crtc->ddp_comp), +- GFP_KERNEL); ++ mtk_crtc->ddp_comp = devm_kcalloc(dev, ++ mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0), ++ sizeof(*mtk_crtc->ddp_comp), ++ GFP_KERNEL); + if (!mtk_crtc->ddp_comp) + return -ENOMEM; + +diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c +index 4f2e3feabc0f8..1bf229615b018 100644 +--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c +@@ -38,6 +38,9 @@ static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, + + size = round_up(size, PAGE_SIZE); + ++ if (size == 0) ++ return ERR_PTR(-EINVAL); ++ + mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL); + if (!mtk_gem_obj) + return ERR_PTR(-ENOMEM); +diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c +index 2a82119eb58ed..2a942dc6a6dc2 100644 +--- a/drivers/gpu/drm/meson/meson_vclk.c ++++ b/drivers/gpu/drm/meson/meson_vclk.c +@@ -790,13 +790,13 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq, + FREQ_1000_1001(params[i].pixel_freq)); + DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n", + i, params[i].phy_freq, +- FREQ_1000_1001(params[i].phy_freq/10)*10); ++ FREQ_1000_1001(params[i].phy_freq/1000)*1000); + /* Match strict frequency */ + if (phy_freq == params[i].phy_freq && + vclk_freq == params[i].vclk_freq) + return MODE_OK; + /* Match 1000/1001 variant */ +- if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) && ++ if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/1000)*1000) && + vclk_freq == FREQ_1000_1001(params[i].vclk_freq)) + return MODE_OK; + } +@@ -1070,7 +1070,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, + + for (freq = 0 ; params[freq].pixel_freq ; ++freq) { + if ((phy_freq == params[freq].phy_freq || +- phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) && ++ phy_freq == FREQ_1000_1001(params[freq].phy_freq/1000)*1000) && + (vclk_freq == params[freq].vclk_freq || + vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) { + if (vclk_freq != params[freq].vclk_freq) +diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c +index adbd5a367395c..707489776e913 100644 +--- a/drivers/gpu/drm/msm/dp/dp_aux.c ++++ b/drivers/gpu/drm/msm/dp/dp_aux.c +@@ -38,6 +38,7 @@ struct dp_aux_private { + bool no_send_stop; + bool initted; + bool is_edp; ++ bool enable_xfers; + u32 offset; + u32 segment; + +@@ -304,6 +305,17 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, + goto exit; + } + ++ /* ++ * If we're using DP and an external display isn't connected then the ++ * transfer won't succeed. Return right away. If we don't do this we ++ * can end up with long timeouts if someone tries to access the DP AUX ++ * character device when no DP device is connected. ++ */ ++ if (!aux->is_edp && !aux->enable_xfers) { ++ ret = -ENXIO; ++ goto exit; ++ } ++ + /* + * For eDP it's important to give a reasonably long wait here for HPD + * to be asserted. This is because the panel driver may have _just_ +@@ -313,7 +325,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, + * avoid ever doing the extra long wait for DP. + */ + if (aux->is_edp) { +- ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog); ++ ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog, ++ 500000); + if (ret) { + DRM_DEBUG_DP("Panel not ready for aux transactions\n"); + goto exit; +@@ -436,6 +449,14 @@ irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux) + return IRQ_HANDLED; + } + ++void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled) ++{ ++ struct dp_aux_private *aux; ++ ++ aux = container_of(dp_aux, struct dp_aux_private, dp_aux); ++ aux->enable_xfers = enabled; ++} ++ + void dp_aux_reconfig(struct drm_dp_aux *dp_aux) + { + struct dp_aux_private *aux; +@@ -513,7 +534,7 @@ static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux, + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + pm_runtime_get_sync(aux->dev); +- ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog); ++ ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog, wait_us); + pm_runtime_put_sync(aux->dev); + + return ret; +diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h +index f47d591c1f54e..4f65e892a8076 100644 +--- a/drivers/gpu/drm/msm/dp/dp_aux.h ++++ b/drivers/gpu/drm/msm/dp/dp_aux.h +@@ -12,6 +12,7 @@ + int dp_aux_register(struct drm_dp_aux *dp_aux); + void dp_aux_unregister(struct drm_dp_aux *dp_aux); + irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux); ++void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled); + void dp_aux_init(struct drm_dp_aux *dp_aux); + void dp_aux_deinit(struct drm_dp_aux *dp_aux); + void dp_aux_reconfig(struct drm_dp_aux *dp_aux); +diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c +index 3e7c84cdef472..628c8181ddd48 100644 +--- a/drivers/gpu/drm/msm/dp/dp_catalog.c ++++ b/drivers/gpu/drm/msm/dp/dp_catalog.c +@@ -263,17 +263,18 @@ void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable) + dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); + } + +-int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog) ++int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog, ++ unsigned long wait_us) + { + u32 state; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + +- /* poll for hpd connected status every 2ms and timeout after 500ms */ ++ /* poll for hpd connected status every 2ms and timeout after wait_us */ + return readl_poll_timeout(catalog->io.aux.base + + REG_DP_DP_HPD_INT_STATUS, + state, state & DP_DP_HPD_STATE_STATUS_CONNECTED, +- 2000, 500000); ++ min(wait_us, 2000), wait_us); + } + + static void dump_regs(void __iomem *base, int len) +diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h +index 75ec290127c77..72a85810607e8 100644 +--- a/drivers/gpu/drm/msm/dp/dp_catalog.h ++++ b/drivers/gpu/drm/msm/dp/dp_catalog.h +@@ -87,7 +87,8 @@ int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read); + int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog); + void dp_catalog_aux_reset(struct dp_catalog *dp_catalog); + void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable); +-int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog); ++int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog, ++ unsigned long wait_us); + u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog); + + /* DP Controller APIs */ +diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c +index c4dda1faef677..112c7e54fc7a6 100644 +--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c ++++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c +@@ -1052,14 +1052,14 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) + if (ret) + return ret; + +- if (voltage_swing_level >= DP_TRAIN_VOLTAGE_SWING_MAX) { ++ if (voltage_swing_level >= DP_TRAIN_LEVEL_MAX) { + drm_dbg_dp(ctrl->drm_dev, + "max. voltage swing level reached %d\n", + voltage_swing_level); + max_level_reached |= DP_TRAIN_MAX_SWING_REACHED; + } + +- if (pre_emphasis_level >= DP_TRAIN_PRE_EMPHASIS_MAX) { ++ if (pre_emphasis_level >= DP_TRAIN_LEVEL_MAX) { + drm_dbg_dp(ctrl->drm_dev, + "max. pre-emphasis level reached %d\n", + pre_emphasis_level); +@@ -1150,7 +1150,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl, + } + + if (ctrl->link->phy_params.v_level >= +- DP_TRAIN_VOLTAGE_SWING_MAX) { ++ DP_TRAIN_LEVEL_MAX) { + DRM_ERROR_RATELIMITED("max v_level reached\n"); + return -EAGAIN; + } +diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c +index ffbfde9225898..36a0ef1cdc1b9 100644 +--- a/drivers/gpu/drm/msm/dp/dp_display.c ++++ b/drivers/gpu/drm/msm/dp/dp_display.c +@@ -555,6 +555,8 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) + int ret; + struct platform_device *pdev = dp->dp_display.pdev; + ++ dp_aux_enable_xfers(dp->aux, true); ++ + mutex_lock(&dp->event_mutex); + + state = dp->hpd_state; +@@ -620,6 +622,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) + u32 state; + struct platform_device *pdev = dp->dp_display.pdev; + ++ dp_aux_enable_xfers(dp->aux, false); ++ + mutex_lock(&dp->event_mutex); + + state = dp->hpd_state; +diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c +index 49dfac1fd1ef2..ea911d9244be7 100644 +--- a/drivers/gpu/drm/msm/dp/dp_link.c ++++ b/drivers/gpu/drm/msm/dp/dp_link.c +@@ -1109,6 +1109,7 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) + int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status) + { + int i; ++ u8 max_p_level; + int v_max = 0, p_max = 0; + struct dp_link_private *link; + +@@ -1140,30 +1141,29 @@ int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status) + * Adjust the voltage swing and pre-emphasis level combination to within + * the allowable range. + */ +- if (dp_link->phy_params.v_level > DP_TRAIN_VOLTAGE_SWING_MAX) { ++ if (dp_link->phy_params.v_level > DP_TRAIN_LEVEL_MAX) { + drm_dbg_dp(link->drm_dev, + "Requested vSwingLevel=%d, change to %d\n", + dp_link->phy_params.v_level, +- DP_TRAIN_VOLTAGE_SWING_MAX); +- dp_link->phy_params.v_level = DP_TRAIN_VOLTAGE_SWING_MAX; ++ DP_TRAIN_LEVEL_MAX); ++ dp_link->phy_params.v_level = DP_TRAIN_LEVEL_MAX; + } + +- if (dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_MAX) { ++ if (dp_link->phy_params.p_level > DP_TRAIN_LEVEL_MAX) { + drm_dbg_dp(link->drm_dev, + "Requested preEmphasisLevel=%d, change to %d\n", + dp_link->phy_params.p_level, +- DP_TRAIN_PRE_EMPHASIS_MAX); +- dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_MAX; ++ DP_TRAIN_LEVEL_MAX); ++ dp_link->phy_params.p_level = DP_TRAIN_LEVEL_MAX; + } + +- if ((dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_LVL_1) +- && (dp_link->phy_params.v_level == +- DP_TRAIN_VOLTAGE_SWING_LVL_2)) { ++ max_p_level = DP_TRAIN_LEVEL_MAX - dp_link->phy_params.v_level; ++ if (dp_link->phy_params.p_level > max_p_level) { + drm_dbg_dp(link->drm_dev, + "Requested preEmphasisLevel=%d, change to %d\n", + dp_link->phy_params.p_level, +- DP_TRAIN_PRE_EMPHASIS_LVL_1); +- dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_LVL_1; ++ max_p_level); ++ dp_link->phy_params.p_level = max_p_level; + } + + drm_dbg_dp(link->drm_dev, "adjusted: v_level=%d, p_level=%d\n", +diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h +index 83da170bc56bf..42aed9c90b732 100644 +--- a/drivers/gpu/drm/msm/dp/dp_link.h ++++ b/drivers/gpu/drm/msm/dp/dp_link.h +@@ -19,19 +19,7 @@ struct dp_link_info { + unsigned long capabilities; + }; + +-enum dp_link_voltage_level { +- DP_TRAIN_VOLTAGE_SWING_LVL_0 = 0, +- DP_TRAIN_VOLTAGE_SWING_LVL_1 = 1, +- DP_TRAIN_VOLTAGE_SWING_LVL_2 = 2, +- DP_TRAIN_VOLTAGE_SWING_MAX = DP_TRAIN_VOLTAGE_SWING_LVL_2, +-}; +- +-enum dp_link_preemaphasis_level { +- DP_TRAIN_PRE_EMPHASIS_LVL_0 = 0, +- DP_TRAIN_PRE_EMPHASIS_LVL_1 = 1, +- DP_TRAIN_PRE_EMPHASIS_LVL_2 = 2, +- DP_TRAIN_PRE_EMPHASIS_MAX = DP_TRAIN_PRE_EMPHASIS_LVL_2, +-}; ++#define DP_TRAIN_LEVEL_MAX 3 + + struct dp_link_test_video { + u32 test_video_pattern; +diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c +index ea10bf81582e9..0f895b8a99d62 100644 +--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c ++++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c +@@ -343,6 +343,9 @@ static int __maybe_unused lcdif_suspend(struct device *dev) + if (ret) + return ret; + ++ if (pm_runtime_suspended(dev)) ++ return 0; ++ + return lcdif_rpm_suspend(dev); + } + +@@ -350,7 +353,8 @@ static int __maybe_unused lcdif_resume(struct device *dev) + { + struct drm_device *drm = dev_get_drvdata(dev); + +- lcdif_rpm_resume(dev); ++ if (!pm_runtime_suspended(dev)) ++ lcdif_rpm_resume(dev); + + return drm_mode_config_helper_resume(drm); + } +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c +index 6a0a4d3b8902d..027867c2a8c5b 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c +@@ -1080,7 +1080,7 @@ r535_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 addr, u8 *data, u8 *psize) + ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl)); + if (ret) { + nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); +- return PTR_ERR(ctrl); ++ return ret; + } + + memcpy(data, ctrl->data, size); +diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig +index b715301ec79f6..6c49270cb290a 100644 +--- a/drivers/gpu/drm/omapdrm/Kconfig ++++ b/drivers/gpu/drm/omapdrm/Kconfig +@@ -4,7 +4,7 @@ config DRM_OMAP + depends on DRM && OF + depends on ARCH_OMAP2PLUS + select DRM_KMS_HELPER +- select FB_DMAMEM_HELPERS if DRM_FBDEV_EMULATION ++ select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION + select VIDEOMODE_HELPERS + select HDMI + default n +diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c +index 6b08b137af1ad..523be34682caf 100644 +--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c ++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c +@@ -51,6 +51,10 @@ static void pan_worker(struct work_struct *work) + omap_gem_roll(bo, fbi->var.yoffset * npages); + } + ++FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(omap_fbdev, ++ drm_fb_helper_damage_range, ++ drm_fb_helper_damage_area) ++ + static int omap_fbdev_pan_display(struct fb_var_screeninfo *var, + struct fb_info *fbi) + { +@@ -78,11 +82,9 @@ static int omap_fbdev_pan_display(struct fb_var_screeninfo *var, + + static int omap_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) + { +- struct drm_fb_helper *helper = info->par; +- struct drm_framebuffer *fb = helper->fb; +- struct drm_gem_object *bo = drm_gem_fb_get_obj(fb, 0); ++ vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + +- return drm_gem_mmap_obj(bo, omap_gem_mmap_size(bo), vma); ++ return fb_deferred_io_mmap(info, vma); + } + + static void omap_fbdev_fb_destroy(struct fb_info *info) +@@ -94,6 +96,7 @@ static void omap_fbdev_fb_destroy(struct fb_info *info) + + DBG(); + ++ fb_deferred_io_cleanup(info); + drm_fb_helper_fini(helper); + + omap_gem_unpin(bo); +@@ -104,15 +107,19 @@ static void omap_fbdev_fb_destroy(struct fb_info *info) + kfree(fbdev); + } + ++/* ++ * For now, we cannot use FB_DEFAULT_DEFERRED_OPS and fb_deferred_io_mmap() ++ * because we use write-combine. ++ */ + static const struct fb_ops omap_fb_ops = { + .owner = THIS_MODULE, +- __FB_DEFAULT_DMAMEM_OPS_RDWR, ++ __FB_DEFAULT_DEFERRED_OPS_RDWR(omap_fbdev), + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_setcmap = drm_fb_helper_setcmap, + .fb_blank = drm_fb_helper_blank, + .fb_pan_display = omap_fbdev_pan_display, +- __FB_DEFAULT_DMAMEM_OPS_DRAW, ++ __FB_DEFAULT_DEFERRED_OPS_DRAW(omap_fbdev), + .fb_ioctl = drm_fb_helper_ioctl, + .fb_mmap = omap_fbdev_fb_mmap, + .fb_destroy = omap_fbdev_fb_destroy, +@@ -213,6 +220,15 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, + fbi->fix.smem_start = dma_addr; + fbi->fix.smem_len = bo->size; + ++ /* deferred I/O */ ++ helper->fbdefio.delay = HZ / 20; ++ helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; ++ ++ fbi->fbdefio = &helper->fbdefio; ++ ret = fb_deferred_io_init(fbi); ++ if (ret) ++ goto fail; ++ + /* if we have DMM, then we can use it for scrolling by just + * shuffling pages around in DMM rather than doing sw blit. + */ +@@ -238,8 +254,20 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, + return ret; + } + ++static int omap_fbdev_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip) ++{ ++ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) ++ return 0; ++ ++ if (helper->fb->funcs->dirty) ++ return helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1); ++ ++ return 0; ++} ++ + static const struct drm_fb_helper_funcs omap_fb_helper_funcs = { + .fb_probe = omap_fbdev_create, ++ .fb_dirty = omap_fbdev_dirty, + }; + + static struct drm_fb_helper *get_fb(struct fb_info *fbi) +diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c +index d58f90bc48fba..745f3e48f02ac 100644 +--- a/drivers/gpu/drm/panel/panel-edp.c ++++ b/drivers/gpu/drm/panel/panel-edp.c +@@ -1865,6 +1865,13 @@ static const struct panel_delay delay_200_500_e50 = { + .enable = 50, + }; + ++static const struct panel_delay delay_200_500_e50_p2e200 = { ++ .hpd_absent = 200, ++ .unprepare = 500, ++ .enable = 50, ++ .prepare_to_enable = 200, ++}; ++ + static const struct panel_delay delay_200_500_e80 = { + .hpd_absent = 200, + .unprepare = 500, +@@ -2034,7 +2041,7 @@ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d6, &delay_200_500_e80_d50, "N140BGA-EA4"), + EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"), + +- EDP_PANEL_ENTRY('C', 'S', 'O', 0x1200, &delay_200_500_e50, "MNC207QS1-1"), ++ EDP_PANEL_ENTRY('C', 'S', 'O', 0x1200, &delay_200_500_e50_p2e200, "MNC207QS1-1"), + + EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d51, &delay_200_500_e200, "Unknown"), + EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5b, &delay_200_500_e200, "Unknown"), +diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +index 9d87cc1a357e3..1a26205701b5e 100644 +--- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c ++++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +@@ -295,8 +295,6 @@ static int ltk050h3148w_init_sequence(struct ltk050h3146w *ctx) + mipi_dsi_dcs_write_seq(dsi, 0xbd, 0x00); + mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xef); + mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x02); +- mipi_dsi_dcs_write_seq(dsi, 0x11); +- mipi_dsi_dcs_write_seq(dsi, 0x29); + + ret = mipi_dsi_dcs_set_tear_on(dsi, 1); + if (ret < 0) { +@@ -326,7 +324,8 @@ static const struct drm_display_mode ltk050h3148w_mode = { + static const struct ltk050h3146w_desc ltk050h3148w_data = { + .mode = <k050h3148w_mode, + .init = ltk050h3148w_init_sequence, +- .mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_VIDEO_BURST, ++ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | ++ MIPI_DSI_MODE_VIDEO_BURST, + }; + + static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx) +diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35950.c b/drivers/gpu/drm/panel/panel-novatek-nt35950.c +index 648ce92014265..028fdac293f77 100644 +--- a/drivers/gpu/drm/panel/panel-novatek-nt35950.c ++++ b/drivers/gpu/drm/panel/panel-novatek-nt35950.c +@@ -556,10 +556,8 @@ static int nt35950_probe(struct mipi_dsi_device *dsi) + } + dsi_r_host = of_find_mipi_dsi_host_by_node(dsi_r); + of_node_put(dsi_r); +- if (!dsi_r_host) { +- dev_err(dev, "Cannot get secondary DSI host\n"); +- return -EPROBE_DEFER; +- } ++ if (!dsi_r_host) ++ return dev_err_probe(dev, -EPROBE_DEFER, "Cannot get secondary DSI host\n"); + + nt->dsi[1] = mipi_dsi_device_register_full(dsi_r_host, info); + if (!nt->dsi[1]) { +diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c +index 76c2a8f6718c8..9c336c71562b9 100644 +--- a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c ++++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c +@@ -109,19 +109,17 @@ static int atana33xc20_resume(struct device *dev) + if (hpd_asserted < 0) + ret = hpd_asserted; + +- if (ret) ++ if (ret) { + dev_warn(dev, "Error waiting for HPD GPIO: %d\n", ret); +- +- return ret; +- } +- +- if (p->aux->wait_hpd_asserted) { ++ goto error; ++ } ++ } else if (p->aux->wait_hpd_asserted) { + ret = p->aux->wait_hpd_asserted(p->aux, HPD_MAX_US); + +- if (ret) ++ if (ret) { + dev_warn(dev, "Controller error waiting for HPD: %d\n", ret); +- +- return ret; ++ goto error; ++ } + } + + /* +@@ -133,6 +131,12 @@ static int atana33xc20_resume(struct device *dev) + * right times. + */ + return 0; ++ ++error: ++ drm_dp_dpcd_set_powered(p->aux, false); ++ regulator_disable(p->supply); ++ ++ return ret; + } + + static int atana33xc20_disable(struct drm_panel *panel) +diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c +index 20e3df1c59d48..e8fe5a69454d0 100644 +--- a/drivers/gpu/drm/panel/panel-simple.c ++++ b/drivers/gpu/drm/panel/panel-simple.c +@@ -2591,6 +2591,9 @@ static const struct panel_desc innolux_g121x1_l03 = { + .unprepare = 200, + .disable = 400, + }, ++ .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, ++ .bus_flags = DRM_BUS_FLAG_DE_HIGH, ++ .connector_type = DRM_MODE_CONNECTOR_LVDS, + }; + + static const struct display_timing innolux_g156hce_l01_timings = { +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index fdd768bbd487c..62ebbdb16253d 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -706,6 +706,8 @@ static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win, + const struct drm_format_info *info; + u16 hor_scl_mode, ver_scl_mode; + u16 hscl_filter_mode, vscl_filter_mode; ++ uint16_t cbcr_src_w = src_w; ++ uint16_t cbcr_src_h = src_h; + u8 gt2 = 0; + u8 gt4 = 0; + u32 val; +@@ -763,27 +765,27 @@ static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win, + vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode); + + if (info->is_yuv) { +- src_w /= info->hsub; +- src_h /= info->vsub; ++ cbcr_src_w /= info->hsub; ++ cbcr_src_h /= info->vsub; + + gt4 = 0; + gt2 = 0; + +- if (src_h >= (4 * dst_h)) { ++ if (cbcr_src_h >= (4 * dst_h)) { + gt4 = 1; +- src_h >>= 2; +- } else if (src_h >= (2 * dst_h)) { ++ cbcr_src_h >>= 2; ++ } else if (cbcr_src_h >= (2 * dst_h)) { + gt2 = 1; +- src_h >>= 1; ++ cbcr_src_h >>= 1; + } + +- hor_scl_mode = scl_get_scl_mode(src_w, dst_w); +- ver_scl_mode = scl_get_scl_mode(src_h, dst_h); ++ hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w); ++ ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h); + +- val = vop2_scale_factor(src_w, dst_w); ++ val = vop2_scale_factor(cbcr_src_w, dst_w); + vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val); + +- val = vop2_scale_factor(src_h, dst_h); ++ val = vop2_scale_factor(cbcr_src_h, dst_h); + vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val); + + vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4); +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index d8751ea203032..5f8d51b293705 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -2740,6 +2740,8 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) + index = 1; + + addr = of_get_address(dev->of_node, index, NULL, NULL); ++ if (!addr) ++ return -EINVAL; + + vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; + vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +index 5b24d5f63701a..c2f9fc1f20a24 100644 +--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c ++++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +@@ -227,6 +227,11 @@ static void amd_sfh_resume(struct amd_mp2_dev *mp2) + struct amd_mp2_sensor_info info; + int i, status; + ++ if (!cl_data->is_any_sensor_enabled) { ++ amd_sfh_clear_intr(mp2); ++ return; ++ } ++ + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_sts[i] == SENSOR_DISABLED) { + info.sensor_idx = cl_data->sensor_idx[i]; +@@ -252,6 +257,11 @@ static void amd_sfh_suspend(struct amd_mp2_dev *mp2) + struct amdtp_cl_data *cl_data = mp2->cl_data; + int i, status; + ++ if (!cl_data->is_any_sensor_enabled) { ++ amd_sfh_clear_intr(mp2); ++ return; ++ } ++ + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] != HPD_IDX && + cl_data->sensor_sts[i] == SENSOR_ENABLED) { +diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c +index 56bd4f02f3191..4b8232360cc46 100644 +--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c ++++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c +@@ -173,6 +173,11 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + + /* request and enable interrupt */ + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); ++ if (ret < 0) { ++ dev_err(dev, "ISH: Failed to allocate IRQ vectors\n"); ++ return ret; ++ } ++ + if (!pdev->msi_enabled && !pdev->msix_enabled) + irq_flag = IRQF_SHARED; + +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index 1e2cd7c8716e8..64ace0b968f07 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -715,8 +715,10 @@ cma_validate_port(struct ib_device *device, u32 port, + rcu_read_lock(); + ndev = rcu_dereference(sgid_attr->ndev); + if (!net_eq(dev_net(ndev), dev_addr->net) || +- ndev->ifindex != bound_if_index) ++ ndev->ifindex != bound_if_index) { ++ rdma_put_gid_attr(sgid_attr); + sgid_attr = ERR_PTR(-ENODEV); ++ } + rcu_read_unlock(); + goto out; + } +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +index 439d0c7c5d0ca..04258676d0726 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +@@ -1013,7 +1013,8 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + hwq_attr.stride = sizeof(struct sq_sge); + hwq_attr.depth = bnxt_qplib_get_depth(sq); + hwq_attr.aux_stride = psn_sz; +- hwq_attr.aux_depth = bnxt_qplib_set_sq_size(sq, qp->wqe_mode); ++ hwq_attr.aux_depth = psn_sz ? bnxt_qplib_set_sq_size(sq, qp->wqe_mode) ++ : 0; + /* Update msn tbl size */ + if (BNXT_RE_HW_RETX(qp->dev_cap_flags) && psn_sz) { + hwq_attr.aux_depth = roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)); +diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c +index 7250d0643b5c5..68e22f368d43a 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_cq.c ++++ b/drivers/infiniband/hw/hns/hns_roce_cq.c +@@ -149,7 +149,7 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) + return ret; + } + +- ret = xa_err(xa_store(&cq_table->array, hr_cq->cqn, hr_cq, GFP_KERNEL)); ++ ret = xa_err(xa_store_irq(&cq_table->array, hr_cq->cqn, hr_cq, GFP_KERNEL)); + if (ret) { + ibdev_err(ibdev, "failed to xa_store CQ, ret = %d.\n", ret); + goto err_put; +@@ -163,7 +163,7 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) + return 0; + + err_xa: +- xa_erase(&cq_table->array, hr_cq->cqn); ++ xa_erase_irq(&cq_table->array, hr_cq->cqn); + err_put: + hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn); + +@@ -182,7 +182,7 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) + dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret, + hr_cq->cqn); + +- xa_erase(&cq_table->array, hr_cq->cqn); ++ xa_erase_irq(&cq_table->array, hr_cq->cqn); + + /* Waiting interrupt process procedure carried out */ + synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq); +@@ -476,13 +476,6 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type) + struct ib_event event; + struct ib_cq *ibcq; + +- hr_cq = xa_load(&hr_dev->cq_table.array, +- cqn & (hr_dev->caps.num_cqs - 1)); +- if (!hr_cq) { +- dev_warn(dev, "async event for bogus CQ 0x%06x\n", cqn); +- return; +- } +- + if (event_type != HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID && + event_type != HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR && + event_type != HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW) { +@@ -491,7 +484,16 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type) + return; + } + +- refcount_inc(&hr_cq->refcount); ++ xa_lock(&hr_dev->cq_table.array); ++ hr_cq = xa_load(&hr_dev->cq_table.array, ++ cqn & (hr_dev->caps.num_cqs - 1)); ++ if (hr_cq) ++ refcount_inc(&hr_cq->refcount); ++ xa_unlock(&hr_dev->cq_table.array); ++ if (!hr_cq) { ++ dev_warn(dev, "async event for bogus CQ 0x%06x\n", cqn); ++ return; ++ } + + ibcq = &hr_cq->ib_cq; + if (ibcq->event_handler) { +diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h +index c3cbd0a494bfd..0b47c6d68804f 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_device.h ++++ b/drivers/infiniband/hw/hns/hns_roce_device.h +@@ -100,6 +100,9 @@ + #define CQ_BANKID_SHIFT 2 + #define CQ_BANKID_MASK GENMASK(1, 0) + ++#define HNS_ROCE_MAX_CQ_COUNT 0xFFFF ++#define HNS_ROCE_MAX_CQ_PERIOD 0xFFFF ++ + enum { + SERV_TYPE_RC, + SERV_TYPE_UC, +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index a4b3f19161dc1..658c522be7583 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -281,7 +281,7 @@ static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, + return hem; + + fail: +- hns_roce_free_hem(hr_dev, hem); ++ kfree(hem); + return NULL; + } + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.h b/drivers/infiniband/hw/hns/hns_roce_hem.h +index 6fb51db9682b8..9c415b2541af8 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.h +@@ -57,16 +57,16 @@ enum { + }; + + #define check_whether_bt_num_3(type, hop_num) \ +- (type < HEM_TYPE_MTT && hop_num == 2) ++ ((type) < HEM_TYPE_MTT && (hop_num) == 2) + + #define check_whether_bt_num_2(type, hop_num) \ +- ((type < HEM_TYPE_MTT && hop_num == 1) || \ +- (type >= HEM_TYPE_MTT && hop_num == 2)) ++ (((type) < HEM_TYPE_MTT && (hop_num) == 1) || \ ++ ((type) >= HEM_TYPE_MTT && (hop_num) == 2)) + + #define check_whether_bt_num_1(type, hop_num) \ +- ((type < HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0) || \ +- (type >= HEM_TYPE_MTT && hop_num == 1) || \ +- (type >= HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0)) ++ (((type) < HEM_TYPE_MTT && (hop_num) == HNS_ROCE_HOP_NUM_0) || \ ++ ((type) >= HEM_TYPE_MTT && (hop_num) == 1) || \ ++ ((type) >= HEM_TYPE_MTT && (hop_num) == HNS_ROCE_HOP_NUM_0)) + + struct hns_roce_hem { + void *buf; +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index ba7ae792d279d..8800464c9a0cd 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -2105,7 +2105,7 @@ static void apply_func_caps(struct hns_roce_dev *hr_dev) + caps->gmv_bt_num * + (HNS_HW_PAGE_SIZE / caps->gmv_entry_sz)); + +- caps->gmv_entry_num = caps->gmv_bt_num * (PAGE_SIZE / ++ caps->gmv_entry_num = caps->gmv_bt_num * (HNS_HW_PAGE_SIZE / + caps->gmv_entry_sz); + } else { + u32 func_num = max_t(u32, 1, hr_dev->func_num); +@@ -3711,8 +3711,9 @@ static void get_cqe_status(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp, + wc->status == IB_WC_WR_FLUSH_ERR)) + return; + +- ibdev_err(&hr_dev->ib_dev, "error cqe status 0x%x:\n", cqe_status); +- print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 4, cqe, ++ ibdev_err_ratelimited(&hr_dev->ib_dev, "error cqe status 0x%x:\n", ++ cqe_status); ++ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 16, 4, cqe, + cq->cqe_size, false); + wc->vendor_err = hr_reg_read(cqe, CQE_SUB_STATUS); + +@@ -5802,7 +5803,7 @@ static int hns_roce_v2_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) + dev_info(hr_dev->dev, + "cq_period(%u) reached the upper limit, adjusted to 65.\n", + cq_period); +- cq_period = HNS_ROCE_MAX_CQ_PERIOD; ++ cq_period = HNS_ROCE_MAX_CQ_PERIOD_HIP08; + } + cq_period *= HNS_ROCE_CLOCK_ADJUST; + } +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +index df04bc8ede57b..dfed6b4ddb04d 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +@@ -1334,7 +1334,7 @@ struct fmea_ram_ecc { + + /* only for RNR timeout issue of HIP08 */ + #define HNS_ROCE_CLOCK_ADJUST 1000 +-#define HNS_ROCE_MAX_CQ_PERIOD 65 ++#define HNS_ROCE_MAX_CQ_PERIOD_HIP08 65 + #define HNS_ROCE_MAX_EQ_PERIOD 65 + #define HNS_ROCE_RNR_TIMER_10NS 1 + #define HNS_ROCE_1US_CFG 999 +diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c +index 1dc60c2b2b7ab..d202258368ed9 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_main.c ++++ b/drivers/infiniband/hw/hns/hns_roce_main.c +@@ -37,9 +37,11 @@ + #include <rdma/ib_smi.h> + #include <rdma/ib_user_verbs.h> + #include <rdma/ib_cache.h> ++#include "hnae3.h" + #include "hns_roce_common.h" + #include "hns_roce_device.h" + #include "hns_roce_hem.h" ++#include "hns_roce_hw_v2.h" + + static int hns_roce_set_mac(struct hns_roce_dev *hr_dev, u32 port, + const u8 *addr) +@@ -192,6 +194,12 @@ static int hns_roce_query_device(struct ib_device *ib_dev, + IB_ATOMIC_HCA : IB_ATOMIC_NONE; + props->max_pkeys = 1; + props->local_ca_ack_delay = hr_dev->caps.local_ca_ack_delay; ++ props->max_ah = INT_MAX; ++ props->cq_caps.max_cq_moderation_period = HNS_ROCE_MAX_CQ_PERIOD; ++ props->cq_caps.max_cq_moderation_count = HNS_ROCE_MAX_CQ_COUNT; ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) ++ props->cq_caps.max_cq_moderation_period = HNS_ROCE_MAX_CQ_PERIOD_HIP08; ++ + if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SRQ) { + props->max_srq = hr_dev->caps.num_srqs; + props->max_srq_wr = hr_dev->caps.max_srq_wrs; +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index 9e05b57a2d67d..80c050d7d0ea6 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -441,18 +441,18 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, + struct ib_device *ibdev = &hr_dev->ib_dev; + struct hns_roce_mr *mr = to_hr_mr(ibmr); + struct hns_roce_mtr *mtr = &mr->pbl_mtr; +- int ret = 0; ++ int ret, sg_num = 0; + + mr->npages = 0; + mr->page_list = kvcalloc(mr->pbl_mtr.hem_cfg.buf_pg_count, + sizeof(dma_addr_t), GFP_KERNEL); + if (!mr->page_list) +- return ret; ++ return sg_num; + +- ret = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page); +- if (ret < 1) { ++ sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page); ++ if (sg_num < 1) { + ibdev_err(ibdev, "failed to store sg pages %u %u, cnt = %d.\n", +- mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, ret); ++ mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, sg_num); + goto err_page_list; + } + +@@ -463,17 +463,16 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, + ret = hns_roce_mtr_map(hr_dev, mtr, mr->page_list, mr->npages); + if (ret) { + ibdev_err(ibdev, "failed to map sg mtr, ret = %d.\n", ret); +- ret = 0; ++ sg_num = 0; + } else { + mr->pbl_mtr.hem_cfg.buf_pg_shift = (u32)ilog2(ibmr->page_size); +- ret = mr->npages; + } + + err_page_list: + kvfree(mr->page_list); + mr->page_list = NULL; + +- return ret; ++ return sg_num; + } + + static void hns_roce_mw_free(struct hns_roce_dev *hr_dev, +diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c +index 4abae94778544..8f48c6723e07e 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_srq.c ++++ b/drivers/infiniband/hw/hns/hns_roce_srq.c +@@ -123,7 +123,7 @@ static int alloc_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) + return ret; + } + +- ret = xa_err(xa_store(&srq_table->xa, srq->srqn, srq, GFP_KERNEL)); ++ ret = xa_err(xa_store_irq(&srq_table->xa, srq->srqn, srq, GFP_KERNEL)); + if (ret) { + ibdev_err(ibdev, "failed to store SRQC, ret = %d.\n", ret); + goto err_put; +@@ -136,7 +136,7 @@ static int alloc_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) + return 0; + + err_xa: +- xa_erase(&srq_table->xa, srq->srqn); ++ xa_erase_irq(&srq_table->xa, srq->srqn); + err_put: + hns_roce_table_put(hr_dev, &srq_table->table, srq->srqn); + +@@ -154,7 +154,7 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) + dev_err(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n", + ret, srq->srqn); + +- xa_erase(&srq_table->xa, srq->srqn); ++ xa_erase_irq(&srq_table->xa, srq->srqn); + + if (refcount_dec_and_test(&srq->refcount)) + complete(&srq->free); +diff --git a/drivers/infiniband/hw/mana/cq.c b/drivers/infiniband/hw/mana/cq.c +index 4a71e678d09c1..89fcc09ded8a4 100644 +--- a/drivers/infiniband/hw/mana/cq.c ++++ b/drivers/infiniband/hw/mana/cq.c +@@ -39,37 +39,13 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, + } + + cq->cqe = attr->cqe; +- cq->umem = ib_umem_get(ibdev, ucmd.buf_addr, cq->cqe * COMP_ENTRY_SIZE, +- IB_ACCESS_LOCAL_WRITE); +- if (IS_ERR(cq->umem)) { +- err = PTR_ERR(cq->umem); +- ibdev_dbg(ibdev, "Failed to get umem for create cq, err %d\n", +- err); +- return err; +- } +- +- err = mana_ib_create_zero_offset_dma_region(mdev, cq->umem, &cq->gdma_region); ++ err = mana_ib_create_queue(mdev, ucmd.buf_addr, cq->cqe * COMP_ENTRY_SIZE, &cq->queue); + if (err) { +- ibdev_dbg(ibdev, +- "Failed to create dma region for create cq, %d\n", +- err); +- goto err_release_umem; ++ ibdev_dbg(ibdev, "Failed to create queue for create cq, %d\n", err); ++ return err; + } + +- ibdev_dbg(ibdev, +- "create_dma_region ret %d gdma_region 0x%llx\n", +- err, cq->gdma_region); +- +- /* +- * The CQ ID is not known at this time. The ID is generated at create_qp +- */ +- cq->id = INVALID_QUEUE_ID; +- + return 0; +- +-err_release_umem: +- ib_umem_release(cq->umem); +- return err; + } + + int mana_ib_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) +@@ -78,24 +54,16 @@ int mana_ib_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) + struct ib_device *ibdev = ibcq->device; + struct mana_ib_dev *mdev; + struct gdma_context *gc; +- int err; + + mdev = container_of(ibdev, struct mana_ib_dev, ib_dev); + gc = mdev_to_gc(mdev); + +- err = mana_ib_gd_destroy_dma_region(mdev, cq->gdma_region); +- if (err) { +- ibdev_dbg(ibdev, +- "Failed to destroy dma region, %d\n", err); +- return err; ++ if (cq->queue.id != INVALID_QUEUE_ID) { ++ kfree(gc->cq_table[cq->queue.id]); ++ gc->cq_table[cq->queue.id] = NULL; + } + +- if (cq->id != INVALID_QUEUE_ID) { +- kfree(gc->cq_table[cq->id]); +- gc->cq_table[cq->id] = NULL; +- } +- +- ib_umem_release(cq->umem); ++ mana_ib_destroy_queue(mdev, &cq->queue); + + return 0; + } +@@ -113,8 +81,10 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq) + struct gdma_context *gc = mdev_to_gc(mdev); + struct gdma_queue *gdma_cq; + ++ if (cq->queue.id >= gc->max_num_cqs) ++ return -EINVAL; + /* Create CQ table entry */ +- WARN_ON(gc->cq_table[cq->id]); ++ WARN_ON(gc->cq_table[cq->queue.id]); + gdma_cq = kzalloc(sizeof(*gdma_cq), GFP_KERNEL); + if (!gdma_cq) + return -ENOMEM; +@@ -122,7 +92,7 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq) + gdma_cq->cq.context = cq; + gdma_cq->type = GDMA_CQ; + gdma_cq->cq.callback = mana_ib_cq_handler; +- gdma_cq->id = cq->id; +- gc->cq_table[cq->id] = gdma_cq; ++ gdma_cq->id = cq->queue.id; ++ gc->cq_table[cq->queue.id] = gdma_cq; + return 0; + } +diff --git a/drivers/infiniband/hw/mana/main.c b/drivers/infiniband/hw/mana/main.c +index 71e33feee61bb..4524c6b807487 100644 +--- a/drivers/infiniband/hw/mana/main.c ++++ b/drivers/infiniband/hw/mana/main.c +@@ -237,6 +237,49 @@ void mana_ib_dealloc_ucontext(struct ib_ucontext *ibcontext) + ibdev_dbg(ibdev, "Failed to destroy doorbell page %d\n", ret); + } + ++int mana_ib_create_queue(struct mana_ib_dev *mdev, u64 addr, u32 size, ++ struct mana_ib_queue *queue) ++{ ++ struct ib_umem *umem; ++ int err; ++ ++ queue->umem = NULL; ++ queue->id = INVALID_QUEUE_ID; ++ queue->gdma_region = GDMA_INVALID_DMA_REGION; ++ ++ umem = ib_umem_get(&mdev->ib_dev, addr, size, IB_ACCESS_LOCAL_WRITE); ++ if (IS_ERR(umem)) { ++ err = PTR_ERR(umem); ++ ibdev_dbg(&mdev->ib_dev, "Failed to get umem, %d\n", err); ++ return err; ++ } ++ ++ err = mana_ib_create_zero_offset_dma_region(mdev, umem, &queue->gdma_region); ++ if (err) { ++ ibdev_dbg(&mdev->ib_dev, "Failed to create dma region, %d\n", err); ++ goto free_umem; ++ } ++ queue->umem = umem; ++ ++ ibdev_dbg(&mdev->ib_dev, ++ "create_dma_region ret %d gdma_region 0x%llx\n", ++ err, queue->gdma_region); ++ ++ return 0; ++free_umem: ++ ib_umem_release(umem); ++ return err; ++} ++ ++void mana_ib_destroy_queue(struct mana_ib_dev *mdev, struct mana_ib_queue *queue) ++{ ++ /* Ignore return code as there is not much we can do about it. ++ * The error message is printed inside. ++ */ ++ mana_ib_gd_destroy_dma_region(mdev, queue->gdma_region); ++ ib_umem_release(queue->umem); ++} ++ + static int + mana_ib_gd_first_dma_region(struct mana_ib_dev *dev, + struct gdma_context *gc, +diff --git a/drivers/infiniband/hw/mana/mana_ib.h b/drivers/infiniband/hw/mana/mana_ib.h +index f83390eebb7d7..6acb5c281c368 100644 +--- a/drivers/infiniband/hw/mana/mana_ib.h ++++ b/drivers/infiniband/hw/mana/mana_ib.h +@@ -45,6 +45,12 @@ struct mana_ib_adapter_caps { + u32 max_inline_data_size; + }; + ++struct mana_ib_queue { ++ struct ib_umem *umem; ++ u64 gdma_region; ++ u64 id; ++}; ++ + struct mana_ib_dev { + struct ib_device ib_dev; + struct gdma_dev *gdma_dev; +@@ -82,10 +88,8 @@ struct mana_ib_mr { + + struct mana_ib_cq { + struct ib_cq ibcq; +- struct ib_umem *umem; ++ struct mana_ib_queue queue; + int cqe; +- u64 gdma_region; +- u64 id; + u32 comp_vector; + }; + +@@ -169,6 +173,10 @@ int mana_ib_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem, + int mana_ib_gd_destroy_dma_region(struct mana_ib_dev *dev, + mana_handle_t gdma_region); + ++int mana_ib_create_queue(struct mana_ib_dev *mdev, u64 addr, u32 size, ++ struct mana_ib_queue *queue); ++void mana_ib_destroy_queue(struct mana_ib_dev *mdev, struct mana_ib_queue *queue); ++ + struct ib_wq *mana_ib_create_wq(struct ib_pd *pd, + struct ib_wq_init_attr *init_attr, + struct ib_udata *udata); +diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c +index 6e7627745c957..d7485ee6a6854 100644 +--- a/drivers/infiniband/hw/mana/qp.c ++++ b/drivers/infiniband/hw/mana/qp.c +@@ -197,7 +197,7 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd, + wq_spec.gdma_region = wq->gdma_region; + wq_spec.queue_size = wq->wq_buf_size; + +- cq_spec.gdma_region = cq->gdma_region; ++ cq_spec.gdma_region = cq->queue.gdma_region; + cq_spec.queue_size = cq->cqe * COMP_ENTRY_SIZE; + cq_spec.modr_ctx_id = 0; + eq = &mpc->ac->eqs[cq->comp_vector % gc->max_num_queues]; +@@ -213,16 +213,16 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd, + + /* The GDMA regions are now owned by the WQ object */ + wq->gdma_region = GDMA_INVALID_DMA_REGION; +- cq->gdma_region = GDMA_INVALID_DMA_REGION; ++ cq->queue.gdma_region = GDMA_INVALID_DMA_REGION; + + wq->id = wq_spec.queue_index; +- cq->id = cq_spec.queue_index; ++ cq->queue.id = cq_spec.queue_index; + + ibdev_dbg(&mdev->ib_dev, + "ret %d rx_object 0x%llx wq id %llu cq id %llu\n", +- ret, wq->rx_object, wq->id, cq->id); ++ ret, wq->rx_object, wq->id, cq->queue.id); + +- resp.entries[i].cqid = cq->id; ++ resp.entries[i].cqid = cq->queue.id; + resp.entries[i].wqid = wq->id; + + mana_ind_table[i] = wq->rx_object; +@@ -232,7 +232,7 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd, + if (ret) + goto fail; + +- gdma_cq_allocated[i] = gc->cq_table[cq->id]; ++ gdma_cq_allocated[i] = gc->cq_table[cq->queue.id]; + } + resp.num_entries = i; + +@@ -264,7 +264,7 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd, + wq = container_of(ibwq, struct mana_ib_wq, ibwq); + cq = container_of(ibcq, struct mana_ib_cq, ibcq); + +- gc->cq_table[cq->id] = NULL; ++ gc->cq_table[cq->queue.id] = NULL; + kfree(gdma_cq_allocated[i]); + + mana_destroy_wq_obj(mpc, GDMA_RQ, wq->rx_object); +@@ -374,7 +374,7 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd, + wq_spec.gdma_region = qp->sq_gdma_region; + wq_spec.queue_size = ucmd.sq_buf_size; + +- cq_spec.gdma_region = send_cq->gdma_region; ++ cq_spec.gdma_region = send_cq->queue.gdma_region; + cq_spec.queue_size = send_cq->cqe * COMP_ENTRY_SIZE; + cq_spec.modr_ctx_id = 0; + eq_vec = send_cq->comp_vector % gc->max_num_queues; +@@ -392,10 +392,10 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd, + + /* The GDMA regions are now owned by the WQ object */ + qp->sq_gdma_region = GDMA_INVALID_DMA_REGION; +- send_cq->gdma_region = GDMA_INVALID_DMA_REGION; ++ send_cq->queue.gdma_region = GDMA_INVALID_DMA_REGION; + + qp->sq_id = wq_spec.queue_index; +- send_cq->id = cq_spec.queue_index; ++ send_cq->queue.id = cq_spec.queue_index; + + /* Create CQ table entry */ + err = mana_ib_install_cq_cb(mdev, send_cq); +@@ -404,10 +404,10 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd, + + ibdev_dbg(&mdev->ib_dev, + "ret %d qp->tx_object 0x%llx sq id %llu cq id %llu\n", err, +- qp->tx_object, qp->sq_id, send_cq->id); ++ qp->tx_object, qp->sq_id, send_cq->queue.id); + + resp.sqid = qp->sq_id; +- resp.cqid = send_cq->id; ++ resp.cqid = send_cq->queue.id; + resp.tx_vp_offset = pd->tx_vp_offset; + + err = ib_copy_to_udata(udata, &resp, sizeof(resp)); +@@ -422,7 +422,7 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd, + + err_release_gdma_cq: + kfree(gdma_cq); +- gc->cq_table[send_cq->id] = NULL; ++ gc->cq_table[send_cq->queue.id] = NULL; + + err_destroy_wq_obj: + mana_destroy_wq_obj(mpc, GDMA_SQ, qp->tx_object); +diff --git a/drivers/infiniband/hw/mlx5/mem.c b/drivers/infiniband/hw/mlx5/mem.c +index 96ffbbaf0a73d..5a22be14d958f 100644 +--- a/drivers/infiniband/hw/mlx5/mem.c ++++ b/drivers/infiniband/hw/mlx5/mem.c +@@ -30,6 +30,7 @@ + * SOFTWARE. + */ + ++#include <linux/io.h> + #include <rdma/ib_umem_odp.h> + #include "mlx5_ib.h" + #include <linux/jiffies.h> +@@ -108,7 +109,6 @@ static int post_send_nop(struct mlx5_ib_dev *dev, struct ib_qp *ibqp, u64 wr_id, + __be32 mmio_wqe[16] = {}; + unsigned long flags; + unsigned int idx; +- int i; + + if (unlikely(dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)) + return -EIO; +@@ -148,10 +148,8 @@ static int post_send_nop(struct mlx5_ib_dev *dev, struct ib_qp *ibqp, u64 wr_id, + * we hit doorbell + */ + wmb(); +- for (i = 0; i < 8; i++) +- mlx5_write64(&mmio_wqe[i * 2], +- bf->bfreg->map + bf->offset + i * 8); +- io_stop_wc(); ++ __iowrite64_copy(bf->bfreg->map + bf->offset, mmio_wqe, ++ sizeof(mmio_wqe) / 8); + + bf->offset ^= bf->buf_size; + +diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h +index a8de35c07c9ef..f255a12e26a02 100644 +--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h ++++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h +@@ -643,9 +643,10 @@ struct mlx5_ib_mkey { + unsigned int ndescs; + struct wait_queue_head wait; + refcount_t usecount; +- /* User Mkey must hold either a rb_key or a cache_ent. */ ++ /* Cacheable user Mkey must hold either a rb_key or a cache_ent. */ + struct mlx5r_cache_rb_key rb_key; + struct mlx5_cache_ent *cache_ent; ++ u8 cacheable : 1; + }; + + #define MLX5_IB_MTT_PRESENT (MLX5_IB_MTT_READ | MLX5_IB_MTT_WRITE) +diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c +index a8ee2ca1f4a17..ecc111ed5d86e 100644 +--- a/drivers/infiniband/hw/mlx5/mr.c ++++ b/drivers/infiniband/hw/mlx5/mr.c +@@ -1158,6 +1158,7 @@ static struct mlx5_ib_mr *alloc_cacheable_mr(struct ib_pd *pd, + if (IS_ERR(mr)) + return mr; + mr->mmkey.rb_key = rb_key; ++ mr->mmkey.cacheable = true; + return mr; + } + +@@ -1168,6 +1169,7 @@ static struct mlx5_ib_mr *alloc_cacheable_mr(struct ib_pd *pd, + mr->ibmr.pd = pd; + mr->umem = umem; + mr->page_shift = order_base_2(page_size); ++ mr->mmkey.cacheable = true; + set_mr_fields(dev, mr, umem->length, access_flags, iova); + + return mr; +@@ -1570,7 +1572,8 @@ static bool can_use_umr_rereg_access(struct mlx5_ib_dev *dev, + unsigned int diffs = current_access_flags ^ target_access_flags; + + if (diffs & ~(IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE | +- IB_ACCESS_REMOTE_READ | IB_ACCESS_RELAXED_ORDERING)) ++ IB_ACCESS_REMOTE_READ | IB_ACCESS_RELAXED_ORDERING | ++ IB_ACCESS_REMOTE_ATOMIC)) + return false; + return mlx5r_umr_can_reconfig(dev, current_access_flags, + target_access_flags); +@@ -1835,6 +1838,23 @@ static int cache_ent_find_and_store(struct mlx5_ib_dev *dev, + return ret; + } + ++static int mlx5_revoke_mr(struct mlx5_ib_mr *mr) ++{ ++ struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device); ++ struct mlx5_cache_ent *ent = mr->mmkey.cache_ent; ++ ++ if (mr->mmkey.cacheable && !mlx5r_umr_revoke_mr(mr) && !cache_ent_find_and_store(dev, mr)) ++ return 0; ++ ++ if (ent) { ++ spin_lock_irq(&ent->mkeys_queue.lock); ++ ent->in_use--; ++ mr->mmkey.cache_ent = NULL; ++ spin_unlock_irq(&ent->mkeys_queue.lock); ++ } ++ return destroy_mkey(dev, mr); ++} ++ + int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) + { + struct mlx5_ib_mr *mr = to_mmr(ibmr); +@@ -1880,16 +1900,9 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) + } + + /* Stop DMA */ +- if (mr->umem && mlx5r_umr_can_load_pas(dev, mr->umem->length)) +- if (mlx5r_umr_revoke_mr(mr) || +- cache_ent_find_and_store(dev, mr)) +- mr->mmkey.cache_ent = NULL; +- +- if (!mr->mmkey.cache_ent) { +- rc = destroy_mkey(to_mdev(mr->ibmr.device), mr); +- if (rc) +- return rc; +- } ++ rc = mlx5_revoke_mr(mr); ++ if (rc) ++ return rc; + + if (mr->umem) { + bool is_odp = is_odp_mr(mr); +diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c +index b78b8c0856abd..c997b7cbf2a9e 100644 +--- a/drivers/infiniband/sw/rxe/rxe_comp.c ++++ b/drivers/infiniband/sw/rxe/rxe_comp.c +@@ -131,12 +131,12 @@ void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb) + { + int must_sched; + +- skb_queue_tail(&qp->resp_pkts, skb); +- +- must_sched = skb_queue_len(&qp->resp_pkts) > 1; ++ must_sched = skb_queue_len(&qp->resp_pkts) > 0; + if (must_sched != 0) + rxe_counter_inc(SKB_TO_PKT(skb)->rxe, RXE_CNT_COMPLETER_SCHED); + ++ skb_queue_tail(&qp->resp_pkts, skb); ++ + if (must_sched) + rxe_sched_task(&qp->comp.task); + else +diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c +index cd59666158b18..e5827064ab1e2 100644 +--- a/drivers/infiniband/sw/rxe/rxe_net.c ++++ b/drivers/infiniband/sw/rxe/rxe_net.c +@@ -366,18 +366,10 @@ static int rxe_send(struct sk_buff *skb, struct rxe_pkt_info *pkt) + rxe_get(pkt->qp); + atomic_inc(&pkt->qp->skb_out); + +- if (skb->protocol == htons(ETH_P_IP)) { ++ if (skb->protocol == htons(ETH_P_IP)) + err = ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb); +- } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ else + err = ip6_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb); +- } else { +- rxe_dbg_qp(pkt->qp, "Unknown layer 3 protocol: %d\n", +- skb->protocol); +- atomic_dec(&pkt->qp->skb_out); +- rxe_put(pkt->qp); +- kfree_skb(skb); +- return -EINVAL; +- } + + if (unlikely(net_xmit_eval(err))) { + rxe_dbg_qp(pkt->qp, "error sending packet: %d\n", err); +diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c +index 614581989b381..a49784e5156c5 100644 +--- a/drivers/infiniband/sw/rxe/rxe_verbs.c ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c +@@ -888,6 +888,7 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, + { + int err = 0; + unsigned long flags; ++ int good = 0; + + spin_lock_irqsave(&qp->sq.sq_lock, flags); + while (ibwr) { +@@ -895,12 +896,15 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, + if (err) { + *bad_wr = ibwr; + break; ++ } else { ++ good++; + } + ibwr = ibwr->next; + } + spin_unlock_irqrestore(&qp->sq.sq_lock, flags); + +- if (!err) ++ /* kickoff processing of any posted wqes */ ++ if (good) + rxe_sched_task(&qp->req.task); + + spin_lock_irqsave(&qp->state_lock, flags); +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +index 4bd161e86f8dd..562df2b3ef187 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +@@ -184,8 +184,12 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) + + ppriv = ipoib_priv(pdev); + +- snprintf(intf_name, sizeof(intf_name), "%s.%04x", +- ppriv->dev->name, pkey); ++ /* If you increase IFNAMSIZ, update snprintf below ++ * to allow longer names. ++ */ ++ BUILD_BUG_ON(IFNAMSIZ != 16); ++ snprintf(intf_name, sizeof(intf_name), "%.10s.%04x", ppriv->dev->name, ++ pkey); + + ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name); + if (IS_ERR(ndev)) { +diff --git a/drivers/input/input.c b/drivers/input/input.c +index 7114854375678..fd4997ba263c7 100644 +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -1378,19 +1378,19 @@ static int input_print_modalias_bits(char *buf, int size, + char name, const unsigned long *bm, + unsigned int min_bit, unsigned int max_bit) + { +- int len = 0, i; ++ int bit = min_bit; ++ int len = 0; + + len += snprintf(buf, max(size, 0), "%c", name); +- for (i = min_bit; i < max_bit; i++) +- if (bm[BIT_WORD(i)] & BIT_MASK(i)) +- len += snprintf(buf + len, max(size - len, 0), "%X,", i); ++ for_each_set_bit_from(bit, bm, max_bit) ++ len += snprintf(buf + len, max(size - len, 0), "%X,", bit); + return len; + } + +-static int input_print_modalias(char *buf, int size, const struct input_dev *id, +- int add_cr) ++static int input_print_modalias_parts(char *buf, int size, int full_len, ++ const struct input_dev *id) + { +- int len; ++ int len, klen, remainder, space; + + len = snprintf(buf, max(size, 0), + "input:b%04Xv%04Xp%04Xe%04X-", +@@ -1399,8 +1399,48 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id, + + len += input_print_modalias_bits(buf + len, size - len, + 'e', id->evbit, 0, EV_MAX); +- len += input_print_modalias_bits(buf + len, size - len, ++ ++ /* ++ * Calculate the remaining space in the buffer making sure we ++ * have place for the terminating 0. ++ */ ++ space = max(size - (len + 1), 0); ++ ++ klen = input_print_modalias_bits(buf + len, size - len, + 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX); ++ len += klen; ++ ++ /* ++ * If we have more data than we can fit in the buffer, check ++ * if we can trim key data to fit in the rest. We will indicate ++ * that key data is incomplete by adding "+" sign at the end, like ++ * this: * "k1,2,3,45,+,". ++ * ++ * Note that we shortest key info (if present) is "k+," so we ++ * can only try to trim if key data is longer than that. ++ */ ++ if (full_len && size < full_len + 1 && klen > 3) { ++ remainder = full_len - len; ++ /* ++ * We can only trim if we have space for the remainder ++ * and also for at least "k+," which is 3 more characters. ++ */ ++ if (remainder <= space - 3) { ++ /* ++ * We are guaranteed to have 'k' in the buffer, so ++ * we need at least 3 additional bytes for storing ++ * "+," in addition to the remainder. ++ */ ++ for (int i = size - 1 - remainder - 3; i >= 0; i--) { ++ if (buf[i] == 'k' || buf[i] == ',') { ++ strcpy(buf + i + 1, "+,"); ++ len = i + 3; /* Not counting '\0' */ ++ break; ++ } ++ } ++ } ++ } ++ + len += input_print_modalias_bits(buf + len, size - len, + 'r', id->relbit, 0, REL_MAX); + len += input_print_modalias_bits(buf + len, size - len, +@@ -1416,12 +1456,25 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id, + len += input_print_modalias_bits(buf + len, size - len, + 'w', id->swbit, 0, SW_MAX); + +- if (add_cr) +- len += snprintf(buf + len, max(size - len, 0), "\n"); +- + return len; + } + ++static int input_print_modalias(char *buf, int size, const struct input_dev *id) ++{ ++ int full_len; ++ ++ /* ++ * Printing is done in 2 passes: first one figures out total length ++ * needed for the modalias string, second one will try to trim key ++ * data in case when buffer is too small for the entire modalias. ++ * If the buffer is too small regardless, it will fill as much as it ++ * can (without trimming key data) into the buffer and leave it to ++ * the caller to figure out what to do with the result. ++ */ ++ full_len = input_print_modalias_parts(NULL, 0, 0, id); ++ return input_print_modalias_parts(buf, size, full_len, id); ++} ++ + static ssize_t input_dev_show_modalias(struct device *dev, + struct device_attribute *attr, + char *buf) +@@ -1429,7 +1482,9 @@ static ssize_t input_dev_show_modalias(struct device *dev, + struct input_dev *id = to_input_dev(dev); + ssize_t len; + +- len = input_print_modalias(buf, PAGE_SIZE, id, 1); ++ len = input_print_modalias(buf, PAGE_SIZE, id); ++ if (len < PAGE_SIZE - 2) ++ len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + + return min_t(int, len, PAGE_SIZE); + } +@@ -1641,6 +1696,23 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, + return 0; + } + ++/* ++ * This is a pretty gross hack. When building uevent data the driver core ++ * may try adding more environment variables to kobj_uevent_env without ++ * telling us, so we have no idea how much of the buffer we can use to ++ * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially ++ * reduce amount of memory we will use for the modalias environment variable. ++ * ++ * The potential additions are: ++ * ++ * SEQNUM=18446744073709551615 - (%llu - 28 bytes) ++ * HOME=/ (6 bytes) ++ * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes) ++ * ++ * 68 bytes total. Allow extra buffer - 96 bytes ++ */ ++#define UEVENT_ENV_EXTRA_LEN 96 ++ + static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, + const struct input_dev *dev) + { +@@ -1650,9 +1722,11 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, + return -ENOMEM; + + len = input_print_modalias(&env->buf[env->buflen - 1], +- sizeof(env->buf) - env->buflen, +- dev, 0); +- if (len >= (sizeof(env->buf) - env->buflen)) ++ (int)sizeof(env->buf) - env->buflen - ++ UEVENT_ENV_EXTRA_LEN, ++ dev); ++ if (len >= ((int)sizeof(env->buf) - env->buflen - ++ UEVENT_ENV_EXTRA_LEN)) + return -ENOMEM; + + env->buflen += len; +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index ac6754a85f350..f440ca440d924 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -2097,6 +2097,8 @@ static int __init iommu_init_pci(struct amd_iommu *iommu) + amd_iommu_max_glx_val = glxval; + else + amd_iommu_max_glx_val = min(amd_iommu_max_glx_val, glxval); ++ ++ iommu_enable_gt(iommu); + } + + if (check_feature(FEATURE_PPR) && alloc_ppr_log(iommu)) +@@ -2773,7 +2775,6 @@ static void early_enable_iommu(struct amd_iommu *iommu) + iommu_enable_command_buffer(iommu); + iommu_enable_event_buffer(iommu); + iommu_set_exclusion_range(iommu); +- iommu_enable_gt(iommu); + iommu_enable_ga(iommu); + iommu_enable_xt(iommu); + iommu_enable_irtcachedis(iommu); +@@ -2830,7 +2831,6 @@ static void early_enable_iommus(void) + iommu_disable_irtcachedis(iommu); + iommu_enable_command_buffer(iommu); + iommu_enable_event_buffer(iommu); +- iommu_enable_gt(iommu); + iommu_enable_ga(iommu); + iommu_enable_xt(iommu); + iommu_enable_irtcachedis(iommu); +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index a7ecd90303dc4..e4a03588a8a0f 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -221,12 +221,11 @@ int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON); + int intel_iommu_enabled = 0; + EXPORT_SYMBOL_GPL(intel_iommu_enabled); + +-static int dmar_map_gfx = 1; + static int intel_iommu_superpage = 1; + static int iommu_identity_mapping; + static int iommu_skip_te_disable; ++static int disable_igfx_iommu; + +-#define IDENTMAP_GFX 2 + #define IDENTMAP_AZALIA 4 + + const struct iommu_ops intel_iommu_ops; +@@ -265,7 +264,7 @@ static int __init intel_iommu_setup(char *str) + no_platform_optin = 1; + pr_info("IOMMU disabled\n"); + } else if (!strncmp(str, "igfx_off", 8)) { +- dmar_map_gfx = 0; ++ disable_igfx_iommu = 1; + pr_info("Disable GFX device mapping\n"); + } else if (!strncmp(str, "forcedac", 8)) { + pr_warn("intel_iommu=forcedac deprecated; use iommu.forcedac instead\n"); +@@ -2402,9 +2401,6 @@ static int device_def_domain_type(struct device *dev) + + if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) + return IOMMU_DOMAIN_IDENTITY; +- +- if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev)) +- return IOMMU_DOMAIN_IDENTITY; + } + + return 0; +@@ -2705,9 +2701,6 @@ static int __init init_dmars(void) + iommu_set_root_entry(iommu); + } + +- if (!dmar_map_gfx) +- iommu_identity_mapping |= IDENTMAP_GFX; +- + check_tylersburg_isoch(); + + ret = si_domain_init(hw_pass_through); +@@ -2798,7 +2791,7 @@ static void __init init_no_remapping_devices(void) + /* This IOMMU has *only* gfx devices. Either bypass it or + set the gfx_mapped flag, as appropriate */ + drhd->gfx_dedicated = 1; +- if (!dmar_map_gfx) ++ if (disable_igfx_iommu) + drhd->ignored = 1; + } + } +@@ -4875,7 +4868,7 @@ static void quirk_iommu_igfx(struct pci_dev *dev) + return; + + pci_info(dev, "Disabling IOMMU for graphics on this chipset\n"); +- dmar_map_gfx = 0; ++ disable_igfx_iommu = 1; + } + + /* G4x/GM45 integrated gfx dmar support is totally busted. */ +@@ -4956,8 +4949,8 @@ static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev) + + if (!(ggc & GGC_MEMORY_VT_ENABLED)) { + pci_info(dev, "BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n"); +- dmar_map_gfx = 0; +- } else if (dmar_map_gfx) { ++ disable_igfx_iommu = 1; ++ } else if (!disable_igfx_iommu) { + /* we have to ensure the gfx device is idle before we flush */ + pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n"); + iommu_set_dma_strict(); +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index a95a483def2d2..659a77f7bb833 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -3317,15 +3317,26 @@ EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed); + static int __iommu_set_group_pasid(struct iommu_domain *domain, + struct iommu_group *group, ioasid_t pasid) + { +- struct group_device *device; +- int ret = 0; ++ struct group_device *device, *last_gdev; ++ int ret; + + for_each_group_device(group, device) { + ret = domain->ops->set_dev_pasid(domain, device->dev, pasid); + if (ret) +- break; ++ goto err_revert; + } + ++ return 0; ++ ++err_revert: ++ last_gdev = device; ++ for_each_group_device(group, device) { ++ const struct iommu_ops *ops = dev_iommu_ops(device->dev); ++ ++ if (device == last_gdev) ++ break; ++ ops->remove_dev_pasid(device->dev, pasid); ++ } + return ret; + } + +@@ -3383,10 +3394,8 @@ int iommu_attach_device_pasid(struct iommu_domain *domain, + } + + ret = __iommu_set_group_pasid(domain, group, pasid); +- if (ret) { +- __iommu_remove_group_pasid(group, pasid); ++ if (ret) + xa_erase(&group->pasid_array, pasid); +- } + out_unlock: + mutex_unlock(&group->mutex); + return ret; +diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c +index 9c8b1349ee17b..a1430ab60a8a3 100644 +--- a/drivers/irqchip/irq-alpine-msi.c ++++ b/drivers/irqchip/irq-alpine-msi.c +@@ -165,7 +165,7 @@ static int alpine_msix_middle_domain_alloc(struct irq_domain *domain, + return 0; + + err_sgi: +- irq_domain_free_irqs_parent(domain, virq, i - 1); ++ irq_domain_free_irqs_parent(domain, virq, i); + alpine_msix_free_sgi(priv, sgi, nr_irqs); + return err; + } +diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c +index 6e1e1f011bb29..dd4d699170f4e 100644 +--- a/drivers/irqchip/irq-loongson-pch-msi.c ++++ b/drivers/irqchip/irq-loongson-pch-msi.c +@@ -136,7 +136,7 @@ static int pch_msi_middle_domain_alloc(struct irq_domain *domain, + + err_hwirq: + pch_msi_free_hwirq(priv, hwirq, nr_irqs); +- irq_domain_free_irqs_parent(domain, virq, i - 1); ++ irq_domain_free_irqs_parent(domain, virq, i); + + return err; + } +diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c +index db9270da5b8e9..b6ddf1d47cb4e 100644 +--- a/drivers/macintosh/via-macii.c ++++ b/drivers/macintosh/via-macii.c +@@ -140,24 +140,19 @@ static int macii_probe(void) + /* Initialize the driver */ + static int macii_init(void) + { +- unsigned long flags; + int err; + +- local_irq_save(flags); +- + err = macii_init_via(); + if (err) +- goto out; ++ return err; + + err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB", + macii_interrupt); + if (err) +- goto out; ++ return err; + + macii_state = idle; +-out: +- local_irq_restore(flags); +- return err; ++ return 0; + } + + /* initialize the hardware */ +diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c +index 5eabdb06c6498..2ac43d1f1b92c 100644 +--- a/drivers/md/dm-delay.c ++++ b/drivers/md/dm-delay.c +@@ -154,8 +154,10 @@ static void delay_dtr(struct dm_target *ti) + { + struct delay_c *dc = ti->private; + +- if (dc->kdelayd_wq) ++ if (dc->kdelayd_wq) { ++ timer_shutdown_sync(&dc->delay_timer); + destroy_workqueue(dc->kdelayd_wq); ++ } + + if (dc->read.dev) + dm_put_device(ti, dc->read.dev); +@@ -240,19 +242,18 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) + ret = delay_class_ctr(ti, &dc->flush, argv); + if (ret) + goto bad; +- max_delay = max(max_delay, dc->write.delay); +- max_delay = max(max_delay, dc->flush.delay); + goto out; + } + + ret = delay_class_ctr(ti, &dc->write, argv + 3); + if (ret) + goto bad; ++ max_delay = max(max_delay, dc->write.delay); ++ + if (argc == 6) { + ret = delay_class_ctr(ti, &dc->flush, argv + 3); + if (ret) + goto bad; +- max_delay = max(max_delay, dc->flush.delay); + goto out; + } + +@@ -267,8 +268,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) + * In case of small requested delays, use kthread instead of + * timers and workqueue to achieve better latency. + */ +- dc->worker = kthread_create(&flush_worker_fn, dc, +- "dm-delay-flush-worker"); ++ dc->worker = kthread_run(&flush_worker_fn, dc, "dm-delay-flush-worker"); + if (IS_ERR(dc->worker)) { + ret = PTR_ERR(dc->worker); + dc->worker = NULL; +@@ -335,7 +335,7 @@ static void delay_presuspend(struct dm_target *ti) + mutex_unlock(&delayed_bios_lock); + + if (!delay_is_fast(dc)) +- del_timer_sync(&dc->delay_timer); ++ timer_delete(&dc->delay_timer); + flush_delayed_bios(dc, true); + } + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 059afc24c08be..0a2d37eb38ef9 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -1424,7 +1424,7 @@ __acquires(bitmap->lock) + sector_t chunk = offset >> bitmap->chunkshift; + unsigned long page = chunk >> PAGE_COUNTER_SHIFT; + unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT; +- sector_t csize; ++ sector_t csize = ((sector_t)1) << bitmap->chunkshift; + int err; + + if (page >= bitmap->pages) { +@@ -1433,6 +1433,7 @@ __acquires(bitmap->lock) + * End-of-device while looking for a whole page or + * user set a huge number to sysfs bitmap_set_bits. + */ ++ *blocks = csize - (offset & (csize - 1)); + return NULL; + } + err = md_bitmap_checkpage(bitmap, page, create, 0); +@@ -1441,8 +1442,7 @@ __acquires(bitmap->lock) + bitmap->bp[page].map == NULL) + csize = ((sector_t)1) << (bitmap->chunkshift + + PAGE_COUNTER_SHIFT); +- else +- csize = ((sector_t)1) << bitmap->chunkshift; ++ + *blocks = csize - (offset & (csize - 1)); + + if (err < 0) +diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c +index f548b1bb75fb9..e932d25ca7b3a 100644 +--- a/drivers/media/i2c/et8ek8/et8ek8_driver.c ++++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c +@@ -1475,7 +1475,7 @@ static int et8ek8_probe(struct i2c_client *client) + return ret; + } + +-static void __exit et8ek8_remove(struct i2c_client *client) ++static void et8ek8_remove(struct i2c_client *client) + { + struct v4l2_subdev *subdev = i2c_get_clientdata(client); + struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev); +@@ -1517,7 +1517,7 @@ static struct i2c_driver et8ek8_i2c_driver = { + .of_match_table = et8ek8_of_table, + }, + .probe = et8ek8_probe, +- .remove = __exit_p(et8ek8_remove), ++ .remove = et8ek8_remove, + .id_table = et8ek8_id_table, + }; + +diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c +index c42adc5a408db..00090e7f5f9da 100644 +--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c ++++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c +@@ -1752,11 +1752,6 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, + + v4l2_async_nf_init(&cio2->notifier, &cio2->v4l2_dev); + +- /* Register notifier for subdevices we care */ +- r = cio2_parse_firmware(cio2); +- if (r) +- goto fail_clean_notifier; +- + r = devm_request_irq(dev, pci_dev->irq, cio2_irq, IRQF_SHARED, + CIO2_NAME, cio2); + if (r) { +@@ -1764,6 +1759,11 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, + goto fail_clean_notifier; + } + ++ /* Register notifier for subdevices we care */ ++ r = cio2_parse_firmware(cio2); ++ if (r) ++ goto fail_clean_notifier; ++ + pm_runtime_put_noidle(dev); + pm_runtime_allow(dev); + +diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c +index 7481f553f9595..24ec576dc3bff 100644 +--- a/drivers/media/pci/ngene/ngene-core.c ++++ b/drivers/media/pci/ngene/ngene-core.c +@@ -1488,7 +1488,9 @@ static int init_channel(struct ngene_channel *chan) + } + + if (dev->ci.en && (io & NGENE_IO_TSOUT)) { +- dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1); ++ ret = dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1); ++ if (ret != 0) ++ goto err; + set_transfer(chan, 1); + chan->dev->channel[2].DataFormatFlags = DF_SWAP32; + set_transfer(&chan->dev->channel[2], 1); +diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c +index 2d7b0508cc9af..6f7d27a48eff0 100644 +--- a/drivers/media/platform/cadence/cdns-csi2rx.c ++++ b/drivers/media/platform/cadence/cdns-csi2rx.c +@@ -239,10 +239,6 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) + + writel(reg, csi2rx->base + CSI2RX_STATIC_CFG_REG); + +- ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true); +- if (ret) +- goto err_disable_pclk; +- + /* Enable DPHY clk and data lanes. */ + if (csi2rx->dphy) { + reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST; +@@ -252,6 +248,13 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) + } + + writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); ++ ++ ret = csi2rx_configure_ext_dphy(csi2rx); ++ if (ret) { ++ dev_err(csi2rx->dev, ++ "Failed to configure external DPHY: %d\n", ret); ++ goto err_disable_pclk; ++ } + } + + /* +@@ -291,14 +294,9 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) + + reset_control_deassert(csi2rx->sys_rst); + +- if (csi2rx->dphy) { +- ret = csi2rx_configure_ext_dphy(csi2rx); +- if (ret) { +- dev_err(csi2rx->dev, +- "Failed to configure external DPHY: %d\n", ret); +- goto err_disable_sysclk; +- } +- } ++ ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true); ++ if (ret) ++ goto err_disable_sysclk; + + clk_disable_unprepare(csi2rx->p_clk); + +@@ -312,6 +310,10 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx) + clk_disable_unprepare(csi2rx->pixel_clk[i - 1]); + } + ++ if (csi2rx->dphy) { ++ writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG); ++ phy_power_off(csi2rx->dphy); ++ } + err_disable_pclk: + clk_disable_unprepare(csi2rx->p_clk); + +diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h +index 792336dada447..997a66318a293 100644 +--- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h ++++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h +@@ -59,7 +59,7 @@ enum rvin_isp_id { + + #define RVIN_REMOTES_MAX \ + (((unsigned int)RVIN_CSI_MAX) > ((unsigned int)RVIN_ISP_MAX) ? \ +- RVIN_CSI_MAX : RVIN_ISP_MAX) ++ (unsigned int)RVIN_CSI_MAX : (unsigned int)RVIN_ISP_MAX) + + /** + * enum rvin_dma_state - DMA states +diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c +index f1c5c0a6a335c..e3e6aa87fe081 100644 +--- a/drivers/media/radio/radio-shark2.c ++++ b/drivers/media/radio/radio-shark2.c +@@ -62,7 +62,7 @@ struct shark_device { + #ifdef SHARK_USE_LEDS + struct work_struct led_work; + struct led_classdev leds[NO_LEDS]; +- char led_names[NO_LEDS][32]; ++ char led_names[NO_LEDS][64]; + atomic_t brightness[NO_LEDS]; + unsigned long brightness_new; + #endif +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index bbd90123a4e76..91a41aa3ced24 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -14,6 +14,7 @@ + #include <linux/module.h> + #include <linux/slab.h> + #include <linux/usb.h> ++#include <linux/usb/quirks.h> + #include <linux/usb/uvc.h> + #include <linux/videodev2.h> + #include <linux/vmalloc.h> +@@ -2232,6 +2233,9 @@ static int uvc_probe(struct usb_interface *intf, + goto error; + } + ++ if (dev->quirks & UVC_QUIRK_NO_RESET_RESUME) ++ udev->quirks &= ~USB_QUIRK_RESET_RESUME; ++ + uvc_dbg(dev, PROBE, "UVC device initialized\n"); + usb_enable_autosuspend(udev); + return 0; +@@ -2574,6 +2578,33 @@ static const struct usb_device_id uvc_ids[] = { + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) }, ++ /* Logitech Rally Bar Huddle */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x046d, ++ .idProduct = 0x087c, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_NO_RESET_RESUME) }, ++ /* Logitech Rally Bar */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x046d, ++ .idProduct = 0x089b, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_NO_RESET_RESUME) }, ++ /* Logitech Rally Bar Mini */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x046d, ++ .idProduct = 0x08d3, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_NO_RESET_RESUME) }, + /* Chicony CNF7129 (Asus EEE 100HE) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, +diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h +index 6fb0a78b1b009..88218693f6f0b 100644 +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -73,6 +73,7 @@ + #define UVC_QUIRK_FORCE_Y8 0x00000800 + #define UVC_QUIRK_FORCE_BPP 0x00001000 + #define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000 ++#define UVC_QUIRK_NO_RESET_RESUME 0x00004000 + + /* Format flags */ + #define UVC_FMT_FLAG_COMPRESSED 0x00000001 +diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c +index 4c6198c48dd61..45836f0a2b0a7 100644 +--- a/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/drivers/media/v4l2-core/v4l2-subdev.c +@@ -732,6 +732,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, + memset(&sel, 0, sizeof(sel)); + sel.which = crop->which; + sel.pad = crop->pad; ++ sel.stream = crop->stream; + sel.target = V4L2_SEL_TGT_CROP; + + rval = v4l2_subdev_call( +@@ -756,6 +757,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, + memset(&sel, 0, sizeof(sel)); + sel.which = crop->which; + sel.pad = crop->pad; ++ sel.stream = crop->stream; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = crop->rect; + +diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile +index 95ef971b5e1cb..b28701138b4bc 100644 +--- a/drivers/misc/lkdtm/Makefile ++++ b/drivers/misc/lkdtm/Makefile +@@ -19,7 +19,7 @@ KASAN_SANITIZE_rodata.o := n + KCSAN_SANITIZE_rodata.o := n + KCOV_INSTRUMENT_rodata.o := n + OBJECT_FILES_NON_STANDARD_rodata.o := y +-CFLAGS_REMOVE_rodata.o += $(CC_FLAGS_LTO) $(RETHUNK_CFLAGS) ++CFLAGS_REMOVE_rodata.o += $(CC_FLAGS_LTO) $(RETHUNK_CFLAGS) $(CC_FLAGS_CFI) + + OBJCOPYFLAGS := + OBJCOPYFLAGS_rodata_objcopy.o := \ +diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c +index b93404d656509..5b861dbff27e9 100644 +--- a/drivers/misc/lkdtm/perms.c ++++ b/drivers/misc/lkdtm/perms.c +@@ -61,7 +61,7 @@ static void *setup_function_descriptor(func_desc_t *fdesc, void *dst) + return fdesc; + } + +-static noinline void execute_location(void *dst, bool write) ++static noinline __nocfi void execute_location(void *dst, bool write) + { + void (*func)(void); + func_desc_t fdesc; +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index 0de87bc638405..6d5c755411de0 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -956,8 +956,10 @@ static int mtd_otp_nvmem_add(struct mtd_info *mtd) + + if (mtd->_get_user_prot_info && mtd->_read_user_prot_reg) { + size = mtd_otp_size(mtd, true); +- if (size < 0) +- return size; ++ if (size < 0) { ++ err = size; ++ goto err; ++ } + + if (size > 0) { + nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size, +diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c +index a74e64e0cfa32..c02e50608816a 100644 +--- a/drivers/mtd/nand/raw/nand_hynix.c ++++ b/drivers/mtd/nand/raw/nand_hynix.c +@@ -401,7 +401,7 @@ static int hynix_nand_rr_init(struct nand_chip *chip) + if (ret) + pr_warn("failed to initialize read-retry infrastructure"); + +- return 0; ++ return ret; + } + + static void hynix_nand_extract_oobsize(struct nand_chip *chip, +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 0918bd6fa81dd..5a202edfec371 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -3146,6 +3146,7 @@ static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip) + static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) + { + struct gpio_desc *gpiod = chip->reset; ++ int err; + + /* If there is a GPIO connected to the reset pin, toggle it */ + if (gpiod) { +@@ -3154,17 +3155,26 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) + * mid-byte, causing the first EEPROM read after the reset + * from the wrong location resulting in the switch booting + * to wrong mode and inoperable. ++ * For this reason, switch families with EEPROM support ++ * generally wait for EEPROM loads to complete as their pre- ++ * and post-reset handlers. + */ +- if (chip->info->ops->get_eeprom) +- mv88e6xxx_g2_eeprom_wait(chip); ++ if (chip->info->ops->hardware_reset_pre) { ++ err = chip->info->ops->hardware_reset_pre(chip); ++ if (err) ++ dev_err(chip->dev, "pre-reset error: %d\n", err); ++ } + + gpiod_set_value_cansleep(gpiod, 1); + usleep_range(10000, 20000); + gpiod_set_value_cansleep(gpiod, 0); + usleep_range(10000, 20000); + +- if (chip->info->ops->get_eeprom) +- mv88e6xxx_g2_eeprom_wait(chip); ++ if (chip->info->ops->hardware_reset_post) { ++ err = chip->info->ops->hardware_reset_post(chip); ++ if (err) ++ dev_err(chip->dev, "post-reset error: %d\n", err); ++ } + } + } + +@@ -4394,6 +4404,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -4584,6 +4596,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { + .watchdog_ops = &mv88e6097_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -4684,6 +4698,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { + .watchdog_ops = &mv88e6097_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -4778,6 +4794,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -4836,6 +4854,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -4892,6 +4912,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -4951,6 +4973,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { + .watchdog_ops = &mv88e6097_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -5004,6 +5028,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { + .watchdog_ops = &mv88e6250_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6250_g1_wait_eeprom_done_prereset, ++ .hardware_reset_post = mv88e6xxx_g1_wait_eeprom_done, + .reset = mv88e6250_g1_reset, + .vtu_getnext = mv88e6185_g1_vtu_getnext, + .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, +@@ -5051,6 +5077,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -5110,6 +5138,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .vtu_getnext = mv88e6185_g1_vtu_getnext, + .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, +@@ -5156,6 +5186,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { + .set_egress_port = mv88e6095_g1_set_egress_port, + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .vtu_getnext = mv88e6185_g1_vtu_getnext, + .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, +@@ -5206,6 +5238,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -5361,6 +5395,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { + .watchdog_ops = &mv88e6097_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6352_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -5423,6 +5459,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -5485,6 +5523,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { + .watchdog_ops = &mv88e6390_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +@@ -5550,6 +5590,8 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { + .watchdog_ops = &mv88e6393x_watchdog_ops, + .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu, + .pot_clear = mv88e6xxx_g2_pot_clear, ++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, ++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, + .reset = mv88e6352_g1_reset, + .rmu_disable = mv88e6390_g1_rmu_disable, + .atu_get_hash = mv88e6165_g1_atu_get_hash, +diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h +index 85eb293381a7e..c34caf9815c5c 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -487,6 +487,12 @@ struct mv88e6xxx_ops { + int (*ppu_enable)(struct mv88e6xxx_chip *chip); + int (*ppu_disable)(struct mv88e6xxx_chip *chip); + ++ /* Additional handlers to run before and after hard reset, to make sure ++ * that the switch and EEPROM are in a good state. ++ */ ++ int (*hardware_reset_pre)(struct mv88e6xxx_chip *chip); ++ int (*hardware_reset_post)(struct mv88e6xxx_chip *chip); ++ + /* Switch Software Reset */ + int (*reset)(struct mv88e6xxx_chip *chip); + +diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c +index 49444a72ff095..9820cd5967574 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1.c ++++ b/drivers/net/dsa/mv88e6xxx/global1.c +@@ -75,6 +75,95 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); + } + ++static int mv88e6250_g1_eeprom_reload(struct mv88e6xxx_chip *chip) ++{ ++ /* MV88E6185_G1_CTL1_RELOAD_EEPROM is also valid for 88E6250 */ ++ int bit = __bf_shf(MV88E6185_G1_CTL1_RELOAD_EEPROM); ++ u16 val; ++ int err; ++ ++ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); ++ if (err) ++ return err; ++ ++ val |= MV88E6185_G1_CTL1_RELOAD_EEPROM; ++ ++ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val); ++ if (err) ++ return err; ++ ++ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_CTL1, bit, 0); ++} ++ ++/* Returns 0 when done, -EBUSY when waiting, other negative codes on error */ ++static int mv88e6xxx_g1_is_eeprom_done(struct mv88e6xxx_chip *chip) ++{ ++ u16 val; ++ int err; ++ ++ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val); ++ if (err < 0) { ++ dev_err(chip->dev, "Error reading status"); ++ return err; ++ } ++ ++ /* If the switch is still resetting, it may not ++ * respond on the bus, and so MDIO read returns ++ * 0xffff. Differentiate between that, and waiting for ++ * the EEPROM to be done by bit 0 being set. ++ */ ++ if (val == 0xffff || !(val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE))) ++ return -EBUSY; ++ ++ return 0; ++} ++ ++/* As the EEInt (EEPROM done) flag clears on read if the status register, this ++ * function must be called directly after a hard reset or EEPROM ReLoad request, ++ * or the done condition may have been missed ++ */ ++int mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip) ++{ ++ const unsigned long timeout = jiffies + 1 * HZ; ++ int ret; ++ ++ /* Wait up to 1 second for the switch to finish reading the ++ * EEPROM. ++ */ ++ while (time_before(jiffies, timeout)) { ++ ret = mv88e6xxx_g1_is_eeprom_done(chip); ++ if (ret != -EBUSY) ++ return ret; ++ } ++ ++ dev_err(chip->dev, "Timeout waiting for EEPROM done"); ++ return -ETIMEDOUT; ++} ++ ++int mv88e6250_g1_wait_eeprom_done_prereset(struct mv88e6xxx_chip *chip) ++{ ++ int ret; ++ ++ ret = mv88e6xxx_g1_is_eeprom_done(chip); ++ if (ret != -EBUSY) ++ return ret; ++ ++ /* Pre-reset, we don't know the state of the switch - when ++ * mv88e6xxx_g1_is_eeprom_done() returns -EBUSY, that may be because ++ * the switch is actually busy reading the EEPROM, or because ++ * MV88E6XXX_G1_STS_IRQ_EEPROM_DONE has been cleared by an unrelated ++ * status register read already. ++ * ++ * To account for the latter case, trigger another EEPROM reload for ++ * another chance at seeing the done flag. ++ */ ++ ret = mv88e6250_g1_eeprom_reload(chip); ++ if (ret) ++ return ret; ++ ++ return mv88e6xxx_g1_wait_eeprom_done(chip); ++} ++ + /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 + * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 + * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 +diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h +index 1095261f5b490..3dbb7a1b8fe11 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1.h ++++ b/drivers/net/dsa/mv88e6xxx/global1.h +@@ -282,6 +282,8 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); + int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); + int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); + int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); ++int mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip); ++int mv88e6250_g1_wait_eeprom_done_prereset(struct mv88e6xxx_chip *chip); + + int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); + int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); +diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c +index 705c3eb19cd3f..d1fbadbf86d4a 100644 +--- a/drivers/net/ethernet/cortina/gemini.c ++++ b/drivers/net/ethernet/cortina/gemini.c +@@ -1107,10 +1107,13 @@ static void gmac_tx_irq_enable(struct net_device *netdev, + { + struct gemini_ethernet_port *port = netdev_priv(netdev); + struct gemini_ethernet *geth = port->geth; ++ unsigned long flags; + u32 val, mask; + + netdev_dbg(netdev, "%s device %d\n", __func__, netdev->dev_id); + ++ spin_lock_irqsave(&geth->irq_lock, flags); ++ + mask = GMAC0_IRQ0_TXQ0_INTS << (6 * netdev->dev_id + txq); + + if (en) +@@ -1119,6 +1122,8 @@ static void gmac_tx_irq_enable(struct net_device *netdev, + val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG); + val = en ? val | mask : val & ~mask; + writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG); ++ ++ spin_unlock_irqrestore(&geth->irq_lock, flags); + } + + static void gmac_tx_irq(struct net_device *netdev, unsigned int txq_num) +@@ -1415,15 +1420,19 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget) + union gmac_rxdesc_3 word3; + struct page *page = NULL; + unsigned int page_offs; ++ unsigned long flags; + unsigned short r, w; + union dma_rwptr rw; + dma_addr_t mapping; + int frag_nr = 0; + ++ spin_lock_irqsave(&geth->irq_lock, flags); + rw.bits32 = readl(ptr_reg); + /* Reset interrupt as all packages until here are taken into account */ + writel(DEFAULT_Q0_INT_BIT << netdev->dev_id, + geth->base + GLOBAL_INTERRUPT_STATUS_1_REG); ++ spin_unlock_irqrestore(&geth->irq_lock, flags); ++ + r = rw.bits.rptr; + w = rw.bits.wptr; + +@@ -1726,10 +1735,9 @@ static irqreturn_t gmac_irq(int irq, void *data) + gmac_update_hw_stats(netdev); + + if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) { ++ spin_lock(&geth->irq_lock); + writel(GMAC0_RXDERR_INT_BIT << (netdev->dev_id * 8), + geth->base + GLOBAL_INTERRUPT_STATUS_4_REG); +- +- spin_lock(&geth->irq_lock); + u64_stats_update_begin(&port->ir_stats_syncp); + ++port->stats.rx_fifo_errors; + u64_stats_update_end(&port->ir_stats_syncp); +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 9f07f4947b631..5c45f42232d32 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -2769,7 +2769,7 @@ static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog, + if (priv->min_num_stack_tx_queues + num_xdp_tx_queues > + priv->num_tx_rings) { + NL_SET_ERR_MSG_FMT_MOD(extack, +- "Reserving %d XDP TXQs does not leave a minimum of %d for stack (total %d)", ++ "Reserving %d XDP TXQs leaves under %d for stack (total %d)", + num_xdp_tx_queues, + priv->min_num_stack_tx_queues, + priv->num_tx_rings); +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 8bd213da8fb6f..a72d8a2eb0b31 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -3674,29 +3674,6 @@ fec_set_mac_address(struct net_device *ndev, void *p) + return 0; + } + +-#ifdef CONFIG_NET_POLL_CONTROLLER +-/** +- * fec_poll_controller - FEC Poll controller function +- * @dev: The FEC network adapter +- * +- * Polled functionality used by netconsole and others in non interrupt mode +- * +- */ +-static void fec_poll_controller(struct net_device *dev) +-{ +- int i; +- struct fec_enet_private *fep = netdev_priv(dev); +- +- for (i = 0; i < FEC_IRQ_NUM; i++) { +- if (fep->irq[i] > 0) { +- disable_irq(fep->irq[i]); +- fec_enet_interrupt(fep->irq[i], dev); +- enable_irq(fep->irq[i]); +- } +- } +-} +-#endif +- + static inline void fec_enet_set_netdev_features(struct net_device *netdev, + netdev_features_t features) + { +@@ -4003,9 +3980,6 @@ static const struct net_device_ops fec_netdev_ops = { + .ndo_tx_timeout = fec_timeout, + .ndo_set_mac_address = fec_set_mac_address, + .ndo_eth_ioctl = phy_do_ioctl_running, +-#ifdef CONFIG_NET_POLL_CONTROLLER +- .ndo_poll_controller = fec_poll_controller, +-#endif + .ndo_set_features = fec_set_features, + .ndo_bpf = fec_enet_bpf, + .ndo_xdp_xmit = fec_enet_xdp_xmit, +diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.c b/drivers/net/ethernet/intel/ice/ice_ddp.c +index fc91c4d411863..4df561d64bc38 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ddp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ddp.c +@@ -1424,14 +1424,14 @@ ice_dwnld_sign_and_cfg_segs(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr, + goto exit; + } + +- conf_idx = le32_to_cpu(seg->signed_seg_idx); +- start = le32_to_cpu(seg->signed_buf_start); + count = le32_to_cpu(seg->signed_buf_count); +- + state = ice_download_pkg_sig_seg(hw, seg); +- if (state) ++ if (state || !count) + goto exit; + ++ conf_idx = le32_to_cpu(seg->signed_seg_idx); ++ start = le32_to_cpu(seg->signed_buf_start); ++ + state = ice_download_pkg_config_seg(hw, pkg_hdr, conf_idx, start, + count); + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c +index 986d429d11755..6972d728431cb 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c +@@ -376,7 +376,8 @@ static int idpf_set_ringparam(struct net_device *netdev, + new_tx_count); + + if (new_tx_count == vport->txq_desc_count && +- new_rx_count == vport->rxq_desc_count) ++ new_rx_count == vport->rxq_desc_count && ++ kring->tcp_data_split == idpf_vport_get_hsplit(vport)) + goto unlock_mutex; + + if (!idpf_vport_set_hsplit(vport, kring->tcp_data_split)) { +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index caa13b9cedff0..d7d73295f0dc4 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -110,16 +110,16 @@ static const struct mtk_reg_map mt7986_reg_map = { + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { +- .rx_ptr = 0x6100, +- .rx_cnt_cfg = 0x6104, +- .pcrx_ptr = 0x6108, +- .glo_cfg = 0x6204, +- .rst_idx = 0x6208, +- .delay_irq = 0x620c, +- .irq_status = 0x6220, +- .irq_mask = 0x6228, +- .adma_rx_dbg0 = 0x6238, +- .int_grp = 0x6250, ++ .rx_ptr = 0x4100, ++ .rx_cnt_cfg = 0x4104, ++ .pcrx_ptr = 0x4108, ++ .glo_cfg = 0x4204, ++ .rst_idx = 0x4208, ++ .delay_irq = 0x420c, ++ .irq_status = 0x4220, ++ .irq_mask = 0x4228, ++ .adma_rx_dbg0 = 0x4238, ++ .int_grp = 0x4250, + }, + .qdma = { + .qtx_cfg = 0x4400, +@@ -1107,7 +1107,7 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd, + rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); + rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -1139,7 +1139,7 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->txrx.txd_size, ++ cnt * soc->tx.desc_size, + ð->phy_scratch_ring, + GFP_KERNEL); + if (unlikely(!eth->scratch_ring)) +@@ -1155,17 +1155,17 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) + if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + +- phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1); ++ phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1); + + for (i = 0; i < cnt; i++) { + dma_addr_t addr = dma_addr + i * MTK_QDMA_PAGE_SIZE; + struct mtk_tx_dma_v2 *txd; + +- txd = eth->scratch_ring + i * soc->txrx.txd_size; ++ txd = eth->scratch_ring + i * soc->tx.desc_size; + txd->txd1 = addr; + if (i < cnt - 1) + txd->txd2 = eth->phy_scratch_ring + +- (i + 1) * soc->txrx.txd_size; ++ (i + 1) * soc->tx.desc_size; + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + if (MTK_HAS_CAPS(soc->caps, MTK_36BIT_DMA)) +@@ -1416,7 +1416,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + memset(itx_buf, 0, sizeof(*itx_buf)); + + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +@@ -1457,7 +1457,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, + + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = min_t(unsigned int, frag_size, +- soc->txrx.dma_max_len); ++ soc->tx.dma_max_len); + txd_info.qid = queue; + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && + !(frag_size - txd_info.size); +@@ -1470,7 +1470,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, + mtk_tx_set_dma_desc(dev, txd, &txd_info); + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +@@ -1513,7 +1513,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1522,7 +1522,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + + /* unmap dma */ + mtk_tx_unmap(eth, tx_buf, NULL, false); +@@ -1547,7 +1547,7 @@ static int mtk_cal_txd_req(struct mtk_eth *eth, struct sk_buff *skb) + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(skb_frag_size(frag), +- eth->soc->txrx.dma_max_len); ++ eth->soc->tx.dma_max_len); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; +@@ -1654,7 +1654,7 @@ static struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth) + + ring = ð->rx_ring[i]; + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + if (rxd->rxd2 & RX_DMA_DONE) { + ring->calc_idx_update = true; + return ring; +@@ -1822,7 +1822,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf, + } + htxd = txd; + +- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + htx_buf = tx_buf; + +@@ -1841,7 +1841,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf, + goto unmap; + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + n_desc++; + } +@@ -1879,7 +1879,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf, + } else { + int idx; + +- idx = txd_to_idx(ring, txd, soc->txrx.txd_size); ++ idx = txd_to_idx(ring, txd, soc->tx.desc_size); + mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), + MT7628_TX_CTX_IDX0); + } +@@ -1890,7 +1890,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf, + + unmap: + while (htxd != txd) { +- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size); + mtk_tx_unmap(eth, tx_buf, NULL, false); + + htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; +@@ -2021,14 +2021,14 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + goto rx_done; + + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + data = ring->data[idx]; + + if (!mtk_rx_get_desc(eth, &trxd, rxd)) + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); + + switch (val) { +@@ -2140,7 +2140,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + skb->dev = netdev; + bytes += skb->len; + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -2156,7 +2156,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + rxdcsum = &trxd.rxd4; + } + +- if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid) ++ if (*rxdcsum & eth->soc->rx.dma_l4_valid) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); +@@ -2280,7 +2280,7 @@ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, + break; + + tx_buf = mtk_desc_to_tx_buf(ring, desc, +- eth->soc->txrx.txd_size); ++ eth->soc->tx.desc_size); + if (!tx_buf->data) + break; + +@@ -2331,7 +2331,7 @@ static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget, + } + mtk_tx_unmap(eth, tx_buf, &bq, true); + +- desc = ring->dma + cpu * eth->soc->txrx.txd_size; ++ desc = ring->dma + cpu * eth->soc->tx.desc_size; + ring->last_free = desc; + atomic_inc(&ring->free_count); + +@@ -2421,7 +2421,7 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget) + do { + int rx_done; + +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, + reg_map->pdma.irq_status); + rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); + rx_done_total += rx_done; +@@ -2437,10 +2437,10 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget) + return budget; + + } while (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask); ++ eth->soc->rx.irq_done_mask); + + if (napi_complete_done(napi, rx_done_total)) +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + + return rx_done_total; + } +@@ -2449,7 +2449,7 @@ static int mtk_tx_alloc(struct mtk_eth *eth) + { + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; +- int i, sz = soc->txrx.txd_size; ++ int i, sz = soc->tx.desc_size; + struct mtk_tx_dma_v2 *txd; + int ring_size; + u32 ofs, val; +@@ -2572,14 +2572,14 @@ static void mtk_tx_clean(struct mtk_eth *eth) + } + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2634,15 +2634,15 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->txrx.rxd_size, +- &ring->phys, GFP_KERNEL); ++ rx_dma_size * eth->soc->rx.desc_size, ++ &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + + ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + } + + if (!ring->dma) +@@ -2653,7 +2653,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + dma_addr_t dma_addr; + void *data; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (ring->page_pool) { + data = mtk_page_pool_get_buff(ring->page_pool, + &dma_addr, GFP_KERNEL); +@@ -2690,7 +2690,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + + rxd->rxd3 = 0; + rxd->rxd4 = 0; +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -2744,7 +2744,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_ + if (!ring->data[i]) + continue; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (!rxd->rxd1) + continue; + +@@ -2761,7 +2761,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_ + + if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->txrx.rxd_size, ++ ring->dma_size * eth->soc->rx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } +@@ -3124,7 +3124,7 @@ static void mtk_dma_free(struct mtk_eth *eth) + netdev_reset_queue(eth->netdev[i]); + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->txrx.txd_size, ++ MTK_QDMA_RING_SIZE * soc->tx.desc_size, + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +@@ -3174,7 +3174,7 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + __napi_schedule(ð->rx_napi); + } + +@@ -3200,9 +3200,9 @@ static irqreturn_t mtk_handle_irq(int irq, void *_eth) + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + + if (mtk_r32(eth, reg_map->pdma.irq_mask) & +- eth->soc->txrx.rx_irq_done_mask) { ++ eth->soc->rx.irq_done_mask) { + if (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask) ++ eth->soc->rx.irq_done_mask) + mtk_handle_irq_rx(irq, _eth); + } + if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { +@@ -3220,10 +3220,10 @@ static void mtk_poll_controller(struct net_device *dev) + struct mtk_eth *eth = mac->hw; + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + mtk_handle_irq_rx(eth->irq[2], dev); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + } + #endif + +@@ -3387,7 +3387,7 @@ static int mtk_open(struct net_device *dev) + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, soc->rx.irq_done_mask); + refcount_set(ð->dma_refcnt, 1); + } + else +@@ -3471,7 +3471,7 @@ static int mtk_stop(struct net_device *dev) + mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + +@@ -3893,7 +3893,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) + else + mtk_hw_reset(eth); + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -3947,9 +3947,9 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) + + /* FE int grouping */ + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->pdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4); + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4); + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + + if (mtk_is_netsys_v3_or_greater(eth)) { +@@ -5039,11 +5039,15 @@ static const struct mtk_soc_data mt2701_data = { + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5059,11 +5063,15 @@ static const struct mtk_soc_data mt7621_data = { + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5081,11 +5089,15 @@ static const struct mtk_soc_data mt7622_data = { + .hash_offset = 2, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5102,11 +5114,15 @@ static const struct mtk_soc_data mt7623_data = { + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5121,11 +5137,15 @@ static const struct mtk_soc_data mt7629_data = { + .required_pctl = false, + .has_accounting = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5143,14 +5163,18 @@ static const struct mtk_soc_data mt7981_data = { + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, + }; + + static const struct mtk_soc_data mt7986_data = { +@@ -5165,14 +5189,18 @@ static const struct mtk_soc_data mt7986_data = { + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, + }; + + static const struct mtk_soc_data mt7988_data = { +@@ -5187,11 +5215,15 @@ static const struct mtk_soc_data mt7988_data = { + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5204,11 +5236,15 @@ static const struct mtk_soc_data rt5350_data = { + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 9ae3b8a71d0e6..39b50de1decbf 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -327,8 +327,8 @@ + /* QDMA descriptor txd3 */ + #define TX_DMA_OWNER_CPU BIT(31) + #define TX_DMA_LS0 BIT(30) +-#define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) ++#define TX_DMA_PLEN0(x) (((x) & eth->soc->tx.dma_max_len) << eth->soc->tx.dma_len_offset) ++#define TX_DMA_PLEN1(x) ((x) & eth->soc->tx.dma_max_len) + #define TX_DMA_SWC BIT(14) + #define TX_DMA_PQID GENMASK(3, 0) + #define TX_DMA_ADDR64_MASK GENMASK(3, 0) +@@ -348,8 +348,8 @@ + /* QDMA descriptor rxd2 */ + #define RX_DMA_DONE BIT(31) + #define RX_DMA_LSO BIT(30) +-#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) ++#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->rx.dma_max_len) << eth->soc->rx.dma_len_offset) ++#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->rx.dma_len_offset) & eth->soc->rx.dma_max_len) + #define RX_DMA_VTAG BIT(15) + #define RX_DMA_ADDR64_MASK GENMASK(3, 0) + #if IS_ENABLED(CONFIG_64BIT) +@@ -1153,10 +1153,9 @@ struct mtk_reg_map { + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +- * @txd_size Tx DMA descriptor size. +- * @rxd_size Rx DMA descriptor size. +- * @rx_irq_done_mask Rx irq done register mask. +- * @rx_dma_l4_valid Rx DMA valid register mask. ++ * @desc_size Tx/Rx DMA descriptor size. ++ * @irq_done_mask Rx irq done register mask. ++ * @dma_l4_valid Rx DMA valid register mask. + * @dma_max_len Max DMA tx/rx buffer length. + * @dma_len_offset Tx/Rx DMA length field offset. + */ +@@ -1174,13 +1173,17 @@ struct mtk_soc_data { + bool has_accounting; + bool disable_pll_modes; + struct { +- u32 txd_size; +- u32 rxd_size; +- u32 rx_irq_done_mask; +- u32 rx_dma_l4_valid; ++ u32 desc_size; + u32 dma_max_len; + u32 dma_len_offset; +- } txrx; ++ } tx; ++ struct { ++ u32 desc_size; ++ u32 irq_done_mask; ++ u32 dma_l4_valid; ++ u32 dma_max_len; ++ u32 dma_len_offset; ++ } rx; + }; + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index 4957412ff1f65..20768ef2e9d2b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -969,19 +969,32 @@ static void cmd_work_handler(struct work_struct *work) + bool poll_cmd = ent->polling; + struct mlx5_cmd_layout *lay; + struct mlx5_core_dev *dev; +- unsigned long cb_timeout; +- struct semaphore *sem; ++ unsigned long timeout; + unsigned long flags; + int alloc_ret; + int cmd_mode; + ++ complete(&ent->handling); ++ + dev = container_of(cmd, struct mlx5_core_dev, cmd); +- cb_timeout = msecs_to_jiffies(mlx5_tout_ms(dev, CMD)); ++ timeout = msecs_to_jiffies(mlx5_tout_ms(dev, CMD)); + +- complete(&ent->handling); +- sem = ent->page_queue ? &cmd->vars.pages_sem : &cmd->vars.sem; +- down(sem); + if (!ent->page_queue) { ++ if (down_timeout(&cmd->vars.sem, timeout)) { ++ mlx5_core_warn(dev, "%s(0x%x) timed out while waiting for a slot.\n", ++ mlx5_command_str(ent->op), ent->op); ++ if (ent->callback) { ++ ent->callback(-EBUSY, ent->context); ++ mlx5_free_cmd_msg(dev, ent->out); ++ free_msg(dev, ent->in); ++ cmd_ent_put(ent); ++ } else { ++ ent->ret = -EBUSY; ++ complete(&ent->done); ++ } ++ complete(&ent->slotted); ++ return; ++ } + alloc_ret = cmd_alloc_index(cmd, ent); + if (alloc_ret < 0) { + mlx5_core_err_rl(dev, "failed to allocate command entry\n"); +@@ -994,10 +1007,11 @@ static void cmd_work_handler(struct work_struct *work) + ent->ret = -EAGAIN; + complete(&ent->done); + } +- up(sem); ++ up(&cmd->vars.sem); + return; + } + } else { ++ down(&cmd->vars.pages_sem); + ent->idx = cmd->vars.max_reg_cmds; + spin_lock_irqsave(&cmd->alloc_lock, flags); + clear_bit(ent->idx, &cmd->vars.bitmask); +@@ -1005,6 +1019,8 @@ static void cmd_work_handler(struct work_struct *work) + spin_unlock_irqrestore(&cmd->alloc_lock, flags); + } + ++ complete(&ent->slotted); ++ + lay = get_inst(cmd, ent->idx); + ent->lay = lay; + memset(lay, 0, sizeof(*lay)); +@@ -1023,7 +1039,7 @@ static void cmd_work_handler(struct work_struct *work) + ent->ts1 = ktime_get_ns(); + cmd_mode = cmd->mode; + +- if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, cb_timeout)) ++ if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, timeout)) + cmd_ent_get(ent); + set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state); + +@@ -1143,6 +1159,9 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) + ent->ret = -ECANCELED; + goto out_err; + } ++ ++ wait_for_completion(&ent->slotted); ++ + if (cmd->mode == CMD_MODE_POLLING || ent->polling) + wait_for_completion(&ent->done); + else if (!wait_for_completion_timeout(&ent->done, timeout)) +@@ -1157,6 +1176,9 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) + } else if (err == -ECANCELED) { + mlx5_core_warn(dev, "%s(0x%x) canceled on out of queue timeout.\n", + mlx5_command_str(ent->op), ent->op); ++ } else if (err == -EBUSY) { ++ mlx5_core_warn(dev, "%s(0x%x) timeout while waiting for command semaphore.\n", ++ mlx5_command_str(ent->op), ent->op); + } + mlx5_core_dbg(dev, "err %d, delivery status %s(%d)\n", + err, deliv_status_to_str(ent->status), ent->status); +@@ -1208,6 +1230,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, + ent->polling = force_polling; + + init_completion(&ent->handling); ++ init_completion(&ent->slotted); + if (!callback) + init_completion(&ent->done); + +@@ -1225,7 +1248,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, + return 0; /* mlx5_cmd_comp_handler() will put(ent) */ + + err = wait_func(dev, ent); +- if (err == -ETIMEDOUT || err == -ECANCELED) ++ if (err == -ETIMEDOUT || err == -ECANCELED || err == -EBUSY) + goto out_free; + + ds = ent->ts2 - ent->ts1; +@@ -1611,6 +1634,9 @@ static int cmd_comp_notifier(struct notifier_block *nb, + dev = container_of(cmd, struct mlx5_core_dev, cmd); + eqe = data; + ++ if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) ++ return NOTIFY_DONE; ++ + mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false); + + return NOTIFY_OK; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +index 06592b9f04242..9240cfe25d102 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +@@ -28,8 +28,10 @@ bool mlx5e_validate_xsk_param(struct mlx5e_params *params, + struct mlx5e_xsk_param *xsk, + struct mlx5_core_dev *mdev) + { +- /* AF_XDP doesn't support frames larger than PAGE_SIZE. */ +- if (xsk->chunk_size > PAGE_SIZE || xsk->chunk_size < MLX5E_MIN_XSK_CHUNK_SIZE) { ++ /* AF_XDP doesn't support frames larger than PAGE_SIZE, ++ * and xsk->chunk_size is limited to 65535 bytes. ++ */ ++ if ((size_t)xsk->chunk_size > PAGE_SIZE || xsk->chunk_size < MLX5E_MIN_XSK_CHUNK_SIZE) { + mlx5_core_err(mdev, "XSK chunk size %u out of bounds [%u, %lu]\n", xsk->chunk_size, + MLX5E_MIN_XSK_CHUNK_SIZE, PAGE_SIZE); + return false; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 319930c04093b..64497b6eebd36 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -6058,7 +6058,7 @@ static int mlx5e_resume(struct auxiliary_device *adev) + return 0; + } + +-static int _mlx5e_suspend(struct auxiliary_device *adev) ++static int _mlx5e_suspend(struct auxiliary_device *adev, bool pre_netdev_reg) + { + struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); + struct mlx5e_priv *priv = mlx5e_dev->priv; +@@ -6067,7 +6067,7 @@ static int _mlx5e_suspend(struct auxiliary_device *adev) + struct mlx5_core_dev *pos; + int i; + +- if (!netif_device_present(netdev)) { ++ if (!pre_netdev_reg && !netif_device_present(netdev)) { + if (test_bit(MLX5E_STATE_DESTROYING, &priv->state)) + mlx5_sd_for_each_dev(i, mdev, pos) + mlx5e_destroy_mdev_resources(pos); +@@ -6090,7 +6090,7 @@ static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state) + + actual_adev = mlx5_sd_get_adev(mdev, adev, edev->idx); + if (actual_adev) +- err = _mlx5e_suspend(actual_adev); ++ err = _mlx5e_suspend(actual_adev, false); + + mlx5_sd_cleanup(mdev); + return err; +@@ -6157,7 +6157,7 @@ static int _mlx5e_probe(struct auxiliary_device *adev) + return 0; + + err_resume: +- _mlx5e_suspend(adev); ++ _mlx5e_suspend(adev, true); + err_profile_cleanup: + profile->cleanup(priv); + err_destroy_netdev: +@@ -6197,7 +6197,7 @@ static void _mlx5e_remove(struct auxiliary_device *adev) + mlx5_core_uplink_netdev_set(mdev, NULL); + mlx5e_dcbnl_delete_app(priv); + unregister_netdev(priv->netdev); +- _mlx5e_suspend(adev); ++ _mlx5e_suspend(adev, false); + priv->profile->cleanup(priv); + mlx5e_destroy_netdev(priv); + mlx5e_devlink_port_unregister(mlx5e_dev); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +index 1b9bc32efd6fa..c5ea1d1d2b035 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +@@ -1874,7 +1874,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_ + "Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n", + addr, vid, vport_num); + NL_SET_ERR_MSG_FMT_MOD(extack, +- "Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n", ++ "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)\n", + addr, vid, vport_num); + return -EINVAL; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +index 349e28a6dd8df..ef55674876cb4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +@@ -833,7 +833,7 @@ int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw, int max_slaves); + void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw); +-int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw); ++int mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw); + + bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev); + void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev); +@@ -925,7 +925,7 @@ mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, + static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; } + + static inline int +-mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw) ++mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw) + { + return 0; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 844d3e3a65ddf..e8caf12f4c4f8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -2502,6 +2502,16 @@ void esw_offloads_cleanup(struct mlx5_eswitch *esw) + esw_offloads_cleanup_reps(esw); + } + ++static int __esw_offloads_load_rep(struct mlx5_eswitch *esw, ++ struct mlx5_eswitch_rep *rep, u8 rep_type) ++{ ++ if (atomic_cmpxchg(&rep->rep_data[rep_type].state, ++ REP_REGISTERED, REP_LOADED) == REP_REGISTERED) ++ return esw->offloads.rep_ops[rep_type]->load(esw->dev, rep); ++ ++ return 0; ++} ++ + static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw, + struct mlx5_eswitch_rep *rep, u8 rep_type) + { +@@ -2526,13 +2536,11 @@ static int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num) + int err; + + rep = mlx5_eswitch_get_rep(esw, vport_num); +- for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) +- if (atomic_cmpxchg(&rep->rep_data[rep_type].state, +- REP_REGISTERED, REP_LOADED) == REP_REGISTERED) { +- err = esw->offloads.rep_ops[rep_type]->load(esw->dev, rep); +- if (err) +- goto err_reps; +- } ++ for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) { ++ err = __esw_offloads_load_rep(esw, rep, rep_type); ++ if (err) ++ goto err_reps; ++ } + + return 0; + +@@ -3277,7 +3285,7 @@ static void esw_destroy_offloads_acl_tables(struct mlx5_eswitch *esw) + esw_vport_destroy_offloads_acl_tables(esw, vport); + } + +-int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw) ++int mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw) + { + struct mlx5_eswitch_rep *rep; + unsigned long i; +@@ -3290,13 +3298,13 @@ int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw) + if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED) + return 0; + +- ret = mlx5_esw_offloads_rep_load(esw, MLX5_VPORT_UPLINK); ++ ret = __esw_offloads_load_rep(esw, rep, REP_IB); + if (ret) + return ret; + + mlx5_esw_for_each_rep(esw, i, rep) { + if (atomic_read(&rep->rep_data[REP_ETH].state) == REP_LOADED) +- mlx5_esw_offloads_rep_load(esw, rep->vport); ++ __esw_offloads_load_rep(esw, rep, REP_IB); + } + + return 0; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index 69d482f7c5a29..37598d116f3b8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -814,7 +814,7 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) + if (shared_fdb) + for (i = 0; i < ldev->ports; i++) + if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) +- mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); ++ mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); + } + + static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) +@@ -922,7 +922,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) + mlx5_rescan_drivers_locked(dev0); + + for (i = 0; i < ldev->ports; i++) { +- err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); ++ err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); + if (err) + break; + } +@@ -933,7 +933,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) + mlx5_deactivate_lag(ldev); + mlx5_lag_add_devices(ldev); + for (i = 0; i < ldev->ports; i++) +- mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); ++ mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); + mlx5_core_err(dev0, "Failed to enable lag\n"); + return; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +index 82889f30506ea..571ea26edd0ca 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +@@ -99,7 +99,7 @@ static int enable_mpesw(struct mlx5_lag *ldev) + dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; + mlx5_rescan_drivers_locked(dev0); + for (i = 0; i < ldev->ports; i++) { +- err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); ++ err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); + if (err) + goto err_rescan_drivers; + } +@@ -113,7 +113,7 @@ static int enable_mpesw(struct mlx5_lag *ldev) + err_add_devices: + mlx5_lag_add_devices(ldev); + for (i = 0; i < ldev->ports; i++) +- mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); ++ mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); + mlx5_mpesw_metadata_cleanup(ldev); + return err; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 331ce47f51a17..6574c145dc1e2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1680,6 +1680,8 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev) + struct devlink *devlink = priv_to_devlink(dev); + int err; + ++ devl_lock(devlink); ++ devl_register(devlink); + dev->state = MLX5_DEVICE_STATE_UP; + err = mlx5_function_enable(dev, true, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT)); + if (err) { +@@ -1693,27 +1695,21 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev) + goto query_hca_caps_err; + } + +- devl_lock(devlink); +- devl_register(devlink); +- + err = mlx5_devlink_params_register(priv_to_devlink(dev)); + if (err) { + mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err); +- goto params_reg_err; ++ goto query_hca_caps_err; + } + + devl_unlock(devlink); + return 0; + +-params_reg_err: +- devl_unregister(devlink); +- devl_unlock(devlink); + query_hca_caps_err: +- devl_unregister(devlink); +- devl_unlock(devlink); + mlx5_function_disable(dev, true); + out: + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; ++ devl_unregister(devlink); ++ devl_unlock(devlink); + return err; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +index 7ebe712808275..b2986175d9afe 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +@@ -60,6 +60,13 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia + goto remap_err; + } + ++ /* Peer devlink logic expects to work on unregistered devlink instance. */ ++ err = mlx5_core_peer_devlink_set(sf_dev, devlink); ++ if (err) { ++ mlx5_core_warn(mdev, "mlx5_core_peer_devlink_set err=%d\n", err); ++ goto peer_devlink_set_err; ++ } ++ + if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev)) + err = mlx5_init_one_light(mdev); + else +@@ -69,20 +76,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia + goto init_one_err; + } + +- err = mlx5_core_peer_devlink_set(sf_dev, devlink); +- if (err) { +- mlx5_core_warn(mdev, "mlx5_core_peer_devlink_set err=%d\n", err); +- goto peer_devlink_set_err; +- } +- + return 0; + +-peer_devlink_set_err: +- if (mlx5_dev_is_lightweight(sf_dev->mdev)) +- mlx5_uninit_one_light(sf_dev->mdev); +- else +- mlx5_uninit_one(sf_dev->mdev); + init_one_err: ++peer_devlink_set_err: + iounmap(mdev->iseg); + remap_err: + mlx5_mdev_uninit(mdev); +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +index 2635ef8958c80..61d88207eed42 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +@@ -1087,8 +1087,6 @@ static int lan966x_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, lan966x); + lan966x->dev = &pdev->dev; + +- lan966x->debugfs_root = debugfs_create_dir("lan966x", NULL); +- + if (!device_get_mac_address(&pdev->dev, mac_addr)) { + ether_addr_copy(lan966x->base_mac, mac_addr); + } else { +@@ -1179,6 +1177,8 @@ static int lan966x_probe(struct platform_device *pdev) + return dev_err_probe(&pdev->dev, -ENODEV, + "no ethernet-ports child found\n"); + ++ lan966x->debugfs_root = debugfs_create_dir("lan966x", NULL); ++ + /* init switch */ + lan966x_init(lan966x); + lan966x_stats_init(lan966x); +@@ -1257,6 +1257,8 @@ static int lan966x_probe(struct platform_device *pdev) + destroy_workqueue(lan966x->stats_queue); + mutex_destroy(&lan966x->stats_lock); + ++ debugfs_remove_recursive(lan966x->debugfs_root); ++ + return err; + } + +diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c +index 2729a2c5acf9c..ca814fe8a775b 100644 +--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c ++++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c +@@ -848,7 +848,7 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len, + } + + if (!wait_for_completion_timeout(&ctx->comp_event, +- (msecs_to_jiffies(hwc->hwc_timeout) * HZ))) { ++ (msecs_to_jiffies(hwc->hwc_timeout)))) { + dev_err(hwc->dev, "HWC: Request timed out!\n"); + err = -ETIMEDOUT; + goto out; +diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c +index c278f8893042b..8159b4c315b5d 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_main.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_main.c +@@ -1206,7 +1206,6 @@ static void qed_slowpath_task(struct work_struct *work) + static int qed_slowpath_wq_start(struct qed_dev *cdev) + { + struct qed_hwfn *hwfn; +- char name[NAME_SIZE]; + int i; + + if (IS_VF(cdev)) +@@ -1215,11 +1214,11 @@ static int qed_slowpath_wq_start(struct qed_dev *cdev) + for_each_hwfn(cdev, i) { + hwfn = &cdev->hwfns[i]; + +- snprintf(name, NAME_SIZE, "slowpath-%02x:%02x.%02x", +- cdev->pdev->bus->number, +- PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id); ++ hwfn->slowpath_wq = alloc_workqueue("slowpath-%02x:%02x.%02x", ++ 0, 0, cdev->pdev->bus->number, ++ PCI_SLOT(cdev->pdev->devfn), ++ hwfn->abs_pf_id); + +- hwfn->slowpath_wq = alloc_workqueue(name, 0, 0); + if (!hwfn->slowpath_wq) { + DP_NOTICE(hwfn, "Cannot create slowpath workqueue\n"); + return -ENOMEM; +diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c +index 0fc5fe564ae50..7df2017c9a8d6 100644 +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -4335,11 +4335,11 @@ static void rtl8169_doorbell(struct rtl8169_private *tp) + static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, + struct net_device *dev) + { +- unsigned int frags = skb_shinfo(skb)->nr_frags; + struct rtl8169_private *tp = netdev_priv(dev); + unsigned int entry = tp->cur_tx % NUM_TX_DESC; + struct TxDesc *txd_first, *txd_last; + bool stop_queue, door_bell; ++ unsigned int frags; + u32 opts[2]; + + if (unlikely(!rtl_tx_slots_avail(tp))) { +@@ -4362,6 +4362,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, + + txd_first = tp->TxDescArray + entry; + ++ frags = skb_shinfo(skb)->nr_frags; + if (frags) { + if (rtl8169_xmit_frags(tp, skb, opts, entry)) + goto err_dma_1; +@@ -4655,10 +4656,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) + rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); + } + +- if (napi_schedule_prep(&tp->napi)) { +- rtl_irq_disable(tp); +- __napi_schedule(&tp->napi); +- } ++ rtl_irq_disable(tp); ++ napi_schedule(&tp->napi); + out: + rtl_ack_events(tp, status); + +diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h +index 46eee747c6992..45ef5ac0788a8 100644 +--- a/drivers/net/ethernet/smsc/smc91x.h ++++ b/drivers/net/ethernet/smsc/smc91x.h +@@ -156,8 +156,8 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) + writew(*wp++, a); + } + +-#define SMC_inw(a, r) _swapw(readw((a) + (r))) +-#define SMC_outw(lp, v, a, r) writew(_swapw(v), (a) + (r)) ++#define SMC_inw(a, r) ioread16be((a) + (r)) ++#define SMC_outw(lp, v, a, r) iowrite16be(v, (a) + (r)) + #define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l) + #define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index dddcaa9220cc3..64b21c83e2b84 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -261,6 +261,8 @@ struct stmmac_priv { + struct stmmac_extra_stats xstats ____cacheline_aligned_in_smp; + struct stmmac_safety_stats sstats; + struct plat_stmmacenet_data *plat; ++ /* Protect est parameters */ ++ struct mutex est_lock; + struct dma_features dma_cap; + struct stmmac_counters mmc; + int hw_cap_support; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +index e04830a3a1fb1..0c5aab6dd7a73 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +@@ -70,11 +70,11 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta) + /* If EST is enabled, disabled it before adjust ptp time. */ + if (priv->plat->est && priv->plat->est->enable) { + est_rst = true; +- mutex_lock(&priv->plat->est->lock); ++ mutex_lock(&priv->est_lock); + priv->plat->est->enable = false; + stmmac_est_configure(priv, priv, priv->plat->est, + priv->plat->clk_ptp_rate); +- mutex_unlock(&priv->plat->est->lock); ++ mutex_unlock(&priv->est_lock); + } + + write_lock_irqsave(&priv->ptp_lock, flags); +@@ -87,7 +87,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta) + ktime_t current_time_ns, basetime; + u64 cycle_time; + +- mutex_lock(&priv->plat->est->lock); ++ mutex_lock(&priv->est_lock); + priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time); + current_time_ns = timespec64_to_ktime(current_time); + time.tv_nsec = priv->plat->est->btr_reserve[0]; +@@ -104,7 +104,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta) + priv->plat->est->enable = true; + ret = stmmac_est_configure(priv, priv, priv->plat->est, + priv->plat->clk_ptp_rate); +- mutex_unlock(&priv->plat->est->lock); ++ mutex_unlock(&priv->est_lock); + if (ret) + netdev_err(priv->dev, "failed to configure EST\n"); + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index cce00719937db..620c16e9be3a6 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -1004,17 +1004,19 @@ static int tc_taprio_configure(struct stmmac_priv *priv, + if (!plat->est) + return -ENOMEM; + +- mutex_init(&priv->plat->est->lock); ++ mutex_init(&priv->est_lock); + } else { ++ mutex_lock(&priv->est_lock); + memset(plat->est, 0, sizeof(*plat->est)); ++ mutex_unlock(&priv->est_lock); + } + + size = qopt->num_entries; + +- mutex_lock(&priv->plat->est->lock); ++ mutex_lock(&priv->est_lock); + priv->plat->est->gcl_size = size; + priv->plat->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE; +- mutex_unlock(&priv->plat->est->lock); ++ mutex_unlock(&priv->est_lock); + + for (i = 0; i < size; i++) { + s64 delta_ns = qopt->entries[i].interval; +@@ -1045,7 +1047,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv, + priv->plat->est->gcl[i] = delta_ns | (gates << wid); + } + +- mutex_lock(&priv->plat->est->lock); ++ mutex_lock(&priv->est_lock); + /* Adjust for real system time */ + priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time); + current_time_ns = timespec64_to_ktime(current_time); +@@ -1068,7 +1070,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv, + tc_taprio_map_maxsdu_txq(priv, qopt); + + if (fpe && !priv->dma_cap.fpesel) { +- mutex_unlock(&priv->plat->est->lock); ++ mutex_unlock(&priv->est_lock); + return -EOPNOTSUPP; + } + +@@ -1079,7 +1081,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv, + + ret = stmmac_est_configure(priv, priv, priv->plat->est, + priv->plat->clk_ptp_rate); +- mutex_unlock(&priv->plat->est->lock); ++ mutex_unlock(&priv->est_lock); + if (ret) { + netdev_err(priv->dev, "failed to configure EST\n"); + goto disable; +@@ -1096,7 +1098,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv, + + disable: + if (priv->plat->est) { +- mutex_lock(&priv->plat->est->lock); ++ mutex_lock(&priv->est_lock); + priv->plat->est->enable = false; + stmmac_est_configure(priv, priv, priv->plat->est, + priv->plat->clk_ptp_rate); +@@ -1105,7 +1107,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv, + priv->xstats.max_sdu_txq_drop[i] = 0; + priv->xstats.mtl_est_txq_hlbf[i] = 0; + } +- mutex_unlock(&priv->plat->est->lock); ++ mutex_unlock(&priv->est_lock); + } + + priv->plat->fpe_cfg->enable = false; +diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c +index 9bd1df8308d24..d3a2fbb14140e 100644 +--- a/drivers/net/ethernet/sun/sungem.c ++++ b/drivers/net/ethernet/sun/sungem.c +@@ -949,17 +949,6 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id) + return IRQ_HANDLED; + } + +-#ifdef CONFIG_NET_POLL_CONTROLLER +-static void gem_poll_controller(struct net_device *dev) +-{ +- struct gem *gp = netdev_priv(dev); +- +- disable_irq(gp->pdev->irq); +- gem_interrupt(gp->pdev->irq, dev); +- enable_irq(gp->pdev->irq); +-} +-#endif +- + static void gem_tx_timeout(struct net_device *dev, unsigned int txqueue) + { + struct gem *gp = netdev_priv(dev); +@@ -2839,9 +2828,6 @@ static const struct net_device_ops gem_netdev_ops = { + .ndo_change_mtu = gem_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = gem_set_mac_address, +-#ifdef CONFIG_NET_POLL_CONTROLLER +- .ndo_poll_controller = gem_poll_controller, +-#endif + }; + + static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c +index b69af69a1ccd3..61ebac7ba6580 100644 +--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c ++++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c +@@ -2152,7 +2152,12 @@ static int prueth_probe(struct platform_device *pdev) + + prueth->registered_netdevs[PRUETH_MAC0] = prueth->emac[PRUETH_MAC0]->ndev; + +- emac_phy_connect(prueth->emac[PRUETH_MAC0]); ++ ret = emac_phy_connect(prueth->emac[PRUETH_MAC0]); ++ if (ret) { ++ dev_err(dev, ++ "can't connect to MII0 PHY, error -%d", ret); ++ goto netdev_unregister; ++ } + phy_attached_info(prueth->emac[PRUETH_MAC0]->ndev->phydev); + } + +@@ -2164,7 +2169,12 @@ static int prueth_probe(struct platform_device *pdev) + } + + prueth->registered_netdevs[PRUETH_MAC1] = prueth->emac[PRUETH_MAC1]->ndev; +- emac_phy_connect(prueth->emac[PRUETH_MAC1]); ++ ret = emac_phy_connect(prueth->emac[PRUETH_MAC1]); ++ if (ret) { ++ dev_err(dev, ++ "can't connect to MII1 PHY, error %d", ret); ++ goto netdev_unregister; ++ } + phy_attached_info(prueth->emac[PRUETH_MAC1]->ndev->phydev); + } + +diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c +index 945c13d1a9829..c09a6f7445754 100644 +--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c ++++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c +@@ -1958,6 +1958,8 @@ int wx_sw_init(struct wx *wx) + return -ENOMEM; + } + ++ bitmap_zero(wx->state, WX_STATE_NBITS); ++ + return 0; + } + EXPORT_SYMBOL(wx_sw_init); +diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c +index 6fae161cbcb82..07ba3a270a14f 100644 +--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c ++++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c +@@ -2690,15 +2690,63 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features) + wx->rss_enabled = false; + } + +- if (changed & +- (NETIF_F_HW_VLAN_CTAG_RX | +- NETIF_F_HW_VLAN_STAG_RX)) ++ netdev->features = features; ++ ++ if (wx->mac.type == wx_mac_sp && changed & NETIF_F_HW_VLAN_CTAG_RX) ++ wx->do_reset(netdev); ++ else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER)) + wx_set_rx_mode(netdev); + +- return 1; ++ return 0; + } + EXPORT_SYMBOL(wx_set_features); + ++#define NETIF_VLAN_STRIPPING_FEATURES (NETIF_F_HW_VLAN_CTAG_RX | \ ++ NETIF_F_HW_VLAN_STAG_RX) ++ ++#define NETIF_VLAN_INSERTION_FEATURES (NETIF_F_HW_VLAN_CTAG_TX | \ ++ NETIF_F_HW_VLAN_STAG_TX) ++ ++#define NETIF_VLAN_FILTERING_FEATURES (NETIF_F_HW_VLAN_CTAG_FILTER | \ ++ NETIF_F_HW_VLAN_STAG_FILTER) ++ ++netdev_features_t wx_fix_features(struct net_device *netdev, ++ netdev_features_t features) ++{ ++ netdev_features_t changed = netdev->features ^ features; ++ struct wx *wx = netdev_priv(netdev); ++ ++ if (changed & NETIF_VLAN_STRIPPING_FEATURES) { ++ if ((features & NETIF_VLAN_STRIPPING_FEATURES) != NETIF_VLAN_STRIPPING_FEATURES && ++ (features & NETIF_VLAN_STRIPPING_FEATURES) != 0) { ++ features &= ~NETIF_VLAN_STRIPPING_FEATURES; ++ features |= netdev->features & NETIF_VLAN_STRIPPING_FEATURES; ++ wx_err(wx, "802.1Q and 802.1ad VLAN stripping must be either both on or both off."); ++ } ++ } ++ ++ if (changed & NETIF_VLAN_INSERTION_FEATURES) { ++ if ((features & NETIF_VLAN_INSERTION_FEATURES) != NETIF_VLAN_INSERTION_FEATURES && ++ (features & NETIF_VLAN_INSERTION_FEATURES) != 0) { ++ features &= ~NETIF_VLAN_INSERTION_FEATURES; ++ features |= netdev->features & NETIF_VLAN_INSERTION_FEATURES; ++ wx_err(wx, "802.1Q and 802.1ad VLAN insertion must be either both on or both off."); ++ } ++ } ++ ++ if (changed & NETIF_VLAN_FILTERING_FEATURES) { ++ if ((features & NETIF_VLAN_FILTERING_FEATURES) != NETIF_VLAN_FILTERING_FEATURES && ++ (features & NETIF_VLAN_FILTERING_FEATURES) != 0) { ++ features &= ~NETIF_VLAN_FILTERING_FEATURES; ++ features |= netdev->features & NETIF_VLAN_FILTERING_FEATURES; ++ wx_err(wx, "802.1Q and 802.1ad VLAN filtering must be either both on or both off."); ++ } ++ } ++ ++ return features; ++} ++EXPORT_SYMBOL(wx_fix_features); ++ + void wx_set_ring(struct wx *wx, u32 new_tx_count, + u32 new_rx_count, struct wx_ring *temp_ring) + { +diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h +index ec909e876720c..c41b29ea812ff 100644 +--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h ++++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h +@@ -30,6 +30,8 @@ int wx_setup_resources(struct wx *wx); + void wx_get_stats64(struct net_device *netdev, + struct rtnl_link_stats64 *stats); + int wx_set_features(struct net_device *netdev, netdev_features_t features); ++netdev_features_t wx_fix_features(struct net_device *netdev, ++ netdev_features_t features); + void wx_set_ring(struct wx *wx, u32 new_tx_count, + u32 new_rx_count, struct wx_ring *temp_ring); + +diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h +index 1fdeb464d5f4a..5aaf7b1fa2db9 100644 +--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h ++++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h +@@ -982,8 +982,13 @@ struct wx_hw_stats { + u64 qmprc; + }; + ++enum wx_state { ++ WX_STATE_RESETTING, ++ WX_STATE_NBITS, /* must be last */ ++}; + struct wx { + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; ++ DECLARE_BITMAP(state, WX_STATE_NBITS); + + void *priv; + u8 __iomem *hw_addr; +@@ -1071,6 +1076,8 @@ struct wx { + u64 hw_csum_rx_good; + u64 hw_csum_rx_error; + u64 alloc_rx_buff_failed; ++ ++ void (*do_reset)(struct net_device *netdev); + }; + + #define WX_INTR_ALL (~0ULL) +@@ -1131,4 +1138,19 @@ static inline struct wx *phylink_to_wx(struct phylink_config *config) + return container_of(config, struct wx, phylink_config); + } + ++static inline int wx_set_state_reset(struct wx *wx) ++{ ++ u8 timeout = 50; ++ ++ while (test_and_set_bit(WX_STATE_RESETTING, wx->state)) { ++ timeout--; ++ if (!timeout) ++ return -EBUSY; ++ ++ usleep_range(1000, 2000); ++ } ++ ++ return 0; ++} ++ + #endif /* _WX_TYPE_H_ */ +diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c +index 786a652ae64f3..46a5a3e952021 100644 +--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c ++++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c +@@ -52,7 +52,7 @@ static int ngbe_set_ringparam(struct net_device *netdev, + struct wx *wx = netdev_priv(netdev); + u32 new_rx_count, new_tx_count; + struct wx_ring *temp_ring; +- int i; ++ int i, err = 0; + + new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD); + new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE); +@@ -64,6 +64,10 @@ static int ngbe_set_ringparam(struct net_device *netdev, + new_rx_count == wx->rx_ring_count) + return 0; + ++ err = wx_set_state_reset(wx); ++ if (err) ++ return err; ++ + if (!netif_running(wx->netdev)) { + for (i = 0; i < wx->num_tx_queues; i++) + wx->tx_ring[i]->count = new_tx_count; +@@ -72,14 +76,16 @@ static int ngbe_set_ringparam(struct net_device *netdev, + wx->tx_ring_count = new_tx_count; + wx->rx_ring_count = new_rx_count; + +- return 0; ++ goto clear_reset; + } + + /* allocate temporary buffer to store rings in */ + i = max_t(int, wx->num_tx_queues, wx->num_rx_queues); + temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL); +- if (!temp_ring) +- return -ENOMEM; ++ if (!temp_ring) { ++ err = -ENOMEM; ++ goto clear_reset; ++ } + + ngbe_down(wx); + +@@ -89,7 +95,9 @@ static int ngbe_set_ringparam(struct net_device *netdev, + wx_configure(wx); + ngbe_up(wx); + +- return 0; ++clear_reset: ++ clear_bit(WX_STATE_RESETTING, wx->state); ++ return err; + } + + static int ngbe_set_channels(struct net_device *dev, +diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +index fdd6b4f70b7a5..e894e01d030d1 100644 +--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c ++++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +@@ -499,6 +499,7 @@ static const struct net_device_ops ngbe_netdev_ops = { + .ndo_start_xmit = wx_xmit_frame, + .ndo_set_rx_mode = wx_set_rx_mode, + .ndo_set_features = wx_set_features, ++ .ndo_fix_features = wx_fix_features, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = wx_set_mac, + .ndo_get_stats64 = wx_get_stats64, +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +index db675512ce4dc..31fde3fa7c6b5 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +@@ -19,7 +19,7 @@ static int txgbe_set_ringparam(struct net_device *netdev, + struct wx *wx = netdev_priv(netdev); + u32 new_rx_count, new_tx_count; + struct wx_ring *temp_ring; +- int i; ++ int i, err = 0; + + new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD); + new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE); +@@ -31,6 +31,10 @@ static int txgbe_set_ringparam(struct net_device *netdev, + new_rx_count == wx->rx_ring_count) + return 0; + ++ err = wx_set_state_reset(wx); ++ if (err) ++ return err; ++ + if (!netif_running(wx->netdev)) { + for (i = 0; i < wx->num_tx_queues; i++) + wx->tx_ring[i]->count = new_tx_count; +@@ -39,14 +43,16 @@ static int txgbe_set_ringparam(struct net_device *netdev, + wx->tx_ring_count = new_tx_count; + wx->rx_ring_count = new_rx_count; + +- return 0; ++ goto clear_reset; + } + + /* allocate temporary buffer to store rings in */ + i = max_t(int, wx->num_tx_queues, wx->num_rx_queues); + temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL); +- if (!temp_ring) +- return -ENOMEM; ++ if (!temp_ring) { ++ err = -ENOMEM; ++ goto clear_reset; ++ } + + txgbe_down(wx); + +@@ -55,7 +61,9 @@ static int txgbe_set_ringparam(struct net_device *netdev, + + txgbe_up(wx); + +- return 0; ++clear_reset: ++ clear_bit(WX_STATE_RESETTING, wx->state); ++ return err; + } + + static int txgbe_set_channels(struct net_device *dev, +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +index bd4624d14ca03..8c7a74981b907 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +@@ -269,6 +269,8 @@ static int txgbe_sw_init(struct wx *wx) + wx->tx_work_limit = TXGBE_DEFAULT_TX_WORK; + wx->rx_work_limit = TXGBE_DEFAULT_RX_WORK; + ++ wx->do_reset = txgbe_do_reset; ++ + return 0; + } + +@@ -421,6 +423,34 @@ int txgbe_setup_tc(struct net_device *dev, u8 tc) + return 0; + } + ++static void txgbe_reinit_locked(struct wx *wx) ++{ ++ int err = 0; ++ ++ netif_trans_update(wx->netdev); ++ ++ err = wx_set_state_reset(wx); ++ if (err) { ++ wx_err(wx, "wait device reset timeout\n"); ++ return; ++ } ++ ++ txgbe_down(wx); ++ txgbe_up(wx); ++ ++ clear_bit(WX_STATE_RESETTING, wx->state); ++} ++ ++void txgbe_do_reset(struct net_device *netdev) ++{ ++ struct wx *wx = netdev_priv(netdev); ++ ++ if (netif_running(netdev)) ++ txgbe_reinit_locked(wx); ++ else ++ txgbe_reset(wx); ++} ++ + static const struct net_device_ops txgbe_netdev_ops = { + .ndo_open = txgbe_open, + .ndo_stop = txgbe_close, +@@ -428,6 +458,7 @@ static const struct net_device_ops txgbe_netdev_ops = { + .ndo_start_xmit = wx_xmit_frame, + .ndo_set_rx_mode = wx_set_rx_mode, + .ndo_set_features = wx_set_features, ++ .ndo_fix_features = wx_fix_features, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = wx_set_mac, + .ndo_get_stats64 = wx_get_stats64, +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +index 1b4ff50d58571..f434a7865cb7b 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +@@ -134,6 +134,7 @@ extern char txgbe_driver_name[]; + void txgbe_down(struct wx *wx); + void txgbe_up(struct wx *wx); + int txgbe_setup_tc(struct net_device *dev, u8 tc); ++void txgbe_do_reset(struct net_device *netdev); + + #define NODE_PROP(_NAME, _PROP) \ + (const struct software_node) { \ +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index ddb50a0e2bc82..87780465cd0d5 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -4676,7 +4676,8 @@ static int lan8841_suspend(struct phy_device *phydev) + struct kszphy_priv *priv = phydev->priv; + struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv; + +- ptp_cancel_worker_sync(ptp_priv->ptp_clock); ++ if (ptp_priv->ptp_clock) ++ ptp_cancel_worker_sync(ptp_priv->ptp_clock); + + return genphy_suspend(phydev); + } +diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c +index 7b8afa589a53c..284375f662f1e 100644 +--- a/drivers/net/usb/aqc111.c ++++ b/drivers/net/usb/aqc111.c +@@ -1141,17 +1141,15 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + continue; + } + +- /* Clone SKB */ +- new_skb = skb_clone(skb, GFP_ATOMIC); ++ new_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len); + + if (!new_skb) + goto err; + +- new_skb->len = pkt_len; ++ skb_put(new_skb, pkt_len); ++ memcpy(new_skb->data, skb->data, pkt_len); + skb_pull(new_skb, AQ_RX_HW_PAD); +- skb_set_tail_pointer(new_skb, new_skb->len); + +- new_skb->truesize = SKB_TRUESIZE(new_skb->len); + if (aqc111_data->rx_checksum) + aqc111_rx_checksum(new_skb, pkt_desc); + +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 2fa46baa589e5..cbea246664795 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -1810,9 +1810,11 @@ static int smsc95xx_reset_resume(struct usb_interface *intf) + + static void smsc95xx_rx_csum_offload(struct sk_buff *skb) + { +- skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2); ++ u16 *csum_ptr = (u16 *)(skb_tail_pointer(skb) - 2); ++ ++ skb->csum = (__force __wsum)get_unaligned(csum_ptr); + skb->ip_summed = CHECKSUM_COMPLETE; +- skb_trim(skb, skb->len - 2); ++ skb_trim(skb, skb->len - 2); /* remove csum */ + } + + static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1870,25 +1872,22 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + if (dev->net->features & NETIF_F_RXCSUM) + smsc95xx_rx_csum_offload(skb); + skb_trim(skb, skb->len - 4); /* remove fcs */ +- skb->truesize = size + sizeof(struct sk_buff); + + return 1; + } + +- ax_skb = skb_clone(skb, GFP_ATOMIC); ++ ax_skb = netdev_alloc_skb_ip_align(dev->net, size); + if (unlikely(!ax_skb)) { + netdev_warn(dev->net, "Error allocating skb\n"); + return 0; + } + +- ax_skb->len = size; +- ax_skb->data = packet; +- skb_set_tail_pointer(ax_skb, size); ++ skb_put(ax_skb, size); ++ memcpy(ax_skb->data, packet, size); + + if (dev->net->features & NETIF_F_RXCSUM) + smsc95xx_rx_csum_offload(ax_skb); + skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ +- ax_skb->truesize = size + sizeof(struct sk_buff); + + usbnet_skb_return(dev, ax_skb); + } +diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c +index 3164451e1010c..0a662e42ed965 100644 +--- a/drivers/net/usb/sr9700.c ++++ b/drivers/net/usb/sr9700.c +@@ -421,19 +421,15 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + skb_pull(skb, 3); + skb->len = len; + skb_set_tail_pointer(skb, len); +- skb->truesize = len + sizeof(struct sk_buff); + return 2; + } + +- /* skb_clone is used for address align */ +- sr_skb = skb_clone(skb, GFP_ATOMIC); ++ sr_skb = netdev_alloc_skb_ip_align(dev->net, len); + if (!sr_skb) + return 0; + +- sr_skb->len = len; +- sr_skb->data = skb->data + 3; +- skb_set_tail_pointer(sr_skb, len); +- sr_skb->truesize = len + sizeof(struct sk_buff); ++ skb_put(sr_skb, len); ++ memcpy(sr_skb->data, skb->data + 3, len); + usbnet_skb_return(dev, sr_skb); + + skb_pull(skb, len + SR_RX_OVERHEAD); +diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c +index 815f8f599f5d1..5a55db349cb57 100644 +--- a/drivers/net/wireless/ath/ar5523/ar5523.c ++++ b/drivers/net/wireless/ath/ar5523/ar5523.c +@@ -1594,6 +1594,20 @@ static int ar5523_probe(struct usb_interface *intf, + struct ar5523 *ar; + int error = -ENOMEM; + ++ static const u8 bulk_ep_addr[] = { ++ AR5523_CMD_TX_PIPE | USB_DIR_OUT, ++ AR5523_DATA_TX_PIPE | USB_DIR_OUT, ++ AR5523_CMD_RX_PIPE | USB_DIR_IN, ++ AR5523_DATA_RX_PIPE | USB_DIR_IN, ++ 0}; ++ ++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr)) { ++ dev_err(&dev->dev, ++ "Could not find all expected endpoints\n"); ++ error = -ENODEV; ++ goto out; ++ } ++ + /* + * Load firmware if the device requires it. This will return + * -ENXIO on success and we'll get called back afer the usb +diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c +index 9ce6f49ab2614..fa5e2e6518313 100644 +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -720,6 +720,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .max_spatial_stream = 4, + .fw = { + .dir = WCN3990_HW_1_0_FW_DIR, ++ .board = WCN3990_HW_1_0_BOARD_DATA_FILE, ++ .board_size = WCN3990_BOARD_DATA_SZ, ++ .board_ext_size = WCN3990_BOARD_EXT_DATA_SZ, + }, + .sw_decrypt_mcast_mgmt = true, + .rx_desc_ops = &wcn3990_rx_desc_ops, +diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c +index 394bf3c32abff..0f6de862c3a9b 100644 +--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c +@@ -439,7 +439,7 @@ ath10k_dbg_sta_write_peer_debug_trigger(struct file *file, + } + out: + mutex_unlock(&ar->conf_mutex); +- return count; ++ return ret ?: count; + } + + static const struct file_operations fops_peer_debug_trigger = { +diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h +index 93c0730919966..9aa2d821b5078 100644 +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -133,6 +133,7 @@ enum qca9377_chip_id_rev { + /* WCN3990 1.0 definitions */ + #define WCN3990_HW_1_0_DEV_VERSION ATH10K_HW_WCN3990 + #define WCN3990_HW_1_0_FW_DIR ATH10K_FW_DIR "/WCN3990/hw1.0" ++#define WCN3990_HW_1_0_BOARD_DATA_FILE "board.bin" + + #define ATH10K_FW_FILE_BASE "firmware" + #define ATH10K_FW_API_MAX 6 +diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h +index ec556bb88d658..ba37e6c7ced08 100644 +--- a/drivers/net/wireless/ath/ath10k/targaddrs.h ++++ b/drivers/net/wireless/ath/ath10k/targaddrs.h +@@ -491,4 +491,7 @@ struct host_interest { + #define QCA4019_BOARD_DATA_SZ 12064 + #define QCA4019_BOARD_EXT_DATA_SZ 0 + ++#define WCN3990_BOARD_DATA_SZ 26328 ++#define WCN3990_BOARD_EXT_DATA_SZ 0 ++ + #endif /* __TARGADDRS_H__ */ +diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c +index 2e9661f4bea82..80d255aaff1be 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -1763,12 +1763,32 @@ void ath10k_wmi_put_wmi_channel(struct ath10k *ar, struct wmi_channel *ch, + + int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) + { +- unsigned long time_left; ++ unsigned long time_left, i; + + time_left = wait_for_completion_timeout(&ar->wmi.service_ready, + WMI_SERVICE_READY_TIMEOUT_HZ); +- if (!time_left) +- return -ETIMEDOUT; ++ if (!time_left) { ++ /* Sometimes the PCI HIF doesn't receive interrupt ++ * for the service ready message even if the buffer ++ * was completed. PCIe sniffer shows that it's ++ * because the corresponding CE ring doesn't fires ++ * it. Workaround here by polling CE rings once. ++ */ ++ ath10k_warn(ar, "failed to receive service ready completion, polling..\n"); ++ ++ for (i = 0; i < CE_COUNT; i++) ++ ath10k_hif_send_complete_check(ar, i, 1); ++ ++ time_left = wait_for_completion_timeout(&ar->wmi.service_ready, ++ WMI_SERVICE_READY_TIMEOUT_HZ); ++ if (!time_left) { ++ ath10k_warn(ar, "polling timed out\n"); ++ return -ETIMEDOUT; ++ } ++ ++ ath10k_warn(ar, "service ready completion received, continuing normally\n"); ++ } ++ + return 0; + } + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 9f4bf41a3d41e..2fca415322aec 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1231,14 +1231,7 @@ static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif) + + enable_ps = arvif->ps; + +- if (!arvif->is_started) { +- /* mac80211 can update vif powersave state while disconnected. +- * Firmware doesn't behave nicely and consumes more power than +- * necessary if PS is disabled on a non-started vdev. Hence +- * force-enable PS for non-running vdevs. +- */ +- psmode = WMI_STA_PS_MODE_ENABLED; +- } else if (enable_ps) { ++ if (enable_ps) { + psmode = WMI_STA_PS_MODE_ENABLED; + param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + +diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c +index 92845ffff44ad..40b6abccbb508 100644 +--- a/drivers/net/wireless/ath/ath12k/qmi.c ++++ b/drivers/net/wireless/ath/ath12k/qmi.c +@@ -3178,6 +3178,9 @@ static const struct qmi_msg_handler ath12k_qmi_msg_handlers[] = { + .decoded_size = sizeof(struct qmi_wlanfw_fw_ready_ind_msg_v01), + .fn = ath12k_qmi_msg_fw_ready_cb, + }, ++ ++ /* end of list */ ++ {}, + }; + + static int ath12k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, +diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c +index 9d69a17699264..34de3d16efc09 100644 +--- a/drivers/net/wireless/ath/ath12k/wmi.c ++++ b/drivers/net/wireless/ath/ath12k/wmi.c +@@ -1900,7 +1900,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd, + if (arg->bw_160) + cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ); + if (arg->bw_320) +- cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ); ++ cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_320MHZ); + + /* Typically if STBC is enabled for VHT it should be enabled + * for HT as well +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index e902ca80eba78..0226c31a6cae2 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -280,7 +280,8 @@ static void carl9170_tx_release(struct kref *ref) + * carl9170_tx_fill_rateinfo() has filled the rate information + * before we get to this point. + */ +- memset_after(&txinfo->status, 0, rates); ++ memset(&txinfo->pad, 0, sizeof(txinfo->pad)); ++ memset(&txinfo->rate_driver_data, 0, sizeof(txinfo->rate_driver_data)); + + if (atomic_read(&ar->tx_total_queued)) + ar->tx_schedule = true; +diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c +index c4edf83559410..a3e03580cd9ff 100644 +--- a/drivers/net/wireless/ath/carl9170/usb.c ++++ b/drivers/net/wireless/ath/carl9170/usb.c +@@ -1069,6 +1069,38 @@ static int carl9170_usb_probe(struct usb_interface *intf, + ar->usb_ep_cmd_is_bulk = true; + } + ++ /* Verify that all expected endpoints are present */ ++ if (ar->usb_ep_cmd_is_bulk) { ++ u8 bulk_ep_addr[] = { ++ AR9170_USB_EP_RX | USB_DIR_IN, ++ AR9170_USB_EP_TX | USB_DIR_OUT, ++ AR9170_USB_EP_CMD | USB_DIR_OUT, ++ 0}; ++ u8 int_ep_addr[] = { ++ AR9170_USB_EP_IRQ | USB_DIR_IN, ++ 0}; ++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) || ++ !usb_check_int_endpoints(intf, int_ep_addr)) ++ err = -ENODEV; ++ } else { ++ u8 bulk_ep_addr[] = { ++ AR9170_USB_EP_RX | USB_DIR_IN, ++ AR9170_USB_EP_TX | USB_DIR_OUT, ++ 0}; ++ u8 int_ep_addr[] = { ++ AR9170_USB_EP_IRQ | USB_DIR_IN, ++ AR9170_USB_EP_CMD | USB_DIR_OUT, ++ 0}; ++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) || ++ !usb_check_int_endpoints(intf, int_ep_addr)) ++ err = -ENODEV; ++ } ++ ++ if (err) { ++ carl9170_free(ar); ++ return err; ++ } ++ + usb_set_intfdata(intf, ar); + SET_IEEE80211_DEV(ar->hw, &intf->dev); + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index d7fb88bb6ae1a..06698a714b523 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1675,6 +1675,15 @@ struct brcmf_random_seed_footer { + #define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de + #define BRCMF_RANDOM_SEED_LENGTH 0x100 + ++static noinline_for_stack void ++brcmf_pcie_provide_random_bytes(struct brcmf_pciedev_info *devinfo, u32 address) ++{ ++ u8 randbuf[BRCMF_RANDOM_SEED_LENGTH]; ++ ++ get_random_bytes(randbuf, BRCMF_RANDOM_SEED_LENGTH); ++ memcpy_toio(devinfo->tcm + address, randbuf, BRCMF_RANDOM_SEED_LENGTH); ++} ++ + static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + const struct firmware *fw, void *nvram, + u32 nvram_len) +@@ -1717,7 +1726,6 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + .length = cpu_to_le32(rand_len), + .magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC), + }; +- void *randbuf; + + /* Some Apple chips/firmwares expect a buffer of random + * data to be present before NVRAM +@@ -1729,10 +1737,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + sizeof(footer)); + + address -= rand_len; +- randbuf = kzalloc(rand_len, GFP_KERNEL); +- get_random_bytes(randbuf, rand_len); +- memcpy_toio(devinfo->tcm + address, randbuf, rand_len); +- kfree(randbuf); ++ brcmf_pcie_provide_random_bytes(devinfo, address); + } + } else { + brcmf_dbg(PCIE, "No matching NVRAM file found %s\n", +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +index 535edb51d1c09..5416e41189657 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2013-2014, 2018-2020, 2022-2023 Intel Corporation ++ * Copyright (C) 2013-2014, 2018-2020, 2022-2024 Intel Corporation + * Copyright (C) 2013-2015 Intel Mobile Communications GmbH + */ + #include <linux/ieee80211.h> +@@ -259,7 +259,6 @@ static void iwl_mvm_bt_coex_enable_esr(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, bool enable) + { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +- int link_id; + + lockdep_assert_held(&mvm->mutex); + +@@ -267,37 +266,22 @@ static void iwl_mvm_bt_coex_enable_esr(struct iwl_mvm *mvm, + return; + + /* Done already */ +- if (mvmvif->bt_coex_esr_disabled == !enable) ++ if ((mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX) == !enable) + return; + +- mvmvif->bt_coex_esr_disabled = !enable; +- +- /* Nothing to do */ +- if (mvmvif->esr_active == enable) +- return; +- +- if (enable) { +- /* Try to re-enable eSR*/ +- iwl_mvm_mld_select_links(mvm, vif, false); +- return; +- } +- +- /* +- * Find the primary link, as we want to switch to it and drop the +- * secondary one. +- */ +- link_id = iwl_mvm_mld_get_primary_link(mvm, vif, vif->active_links); +- WARN_ON(link_id < 0); ++ if (enable) ++ mvmvif->esr_disable_reason &= ~IWL_MVM_ESR_DISABLE_COEX; ++ else ++ mvmvif->esr_disable_reason |= IWL_MVM_ESR_DISABLE_COEX; + +- ieee80211_set_active_links_async(vif, +- vif->active_links & BIT(link_id)); ++ iwl_mvm_recalc_esr(mvm, vif); + } + + /* + * This function receives the LB link id and checks if eSR should be + * enabled or disabled (due to BT coex) + */ +-bool ++static bool + iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + int link_id, int primary_link) +@@ -338,7 +322,7 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, + if (!link_rssi) + wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi; + +- else if (!mvmvif->bt_coex_esr_disabled) ++ else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX)) + /* RSSI needs to get really low to disable eSR... */ + wifi_loss_rate = + link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ? +@@ -354,9 +338,9 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, + return wifi_loss_rate <= IWL_MVM_BT_COEX_WIFI_LOSS_THRESH; + } + +-void iwl_mvm_bt_coex_update_vif_esr(struct iwl_mvm *mvm, +- struct ieee80211_vif *vif, +- int link_id) ++void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm, ++ struct ieee80211_vif *vif, ++ int link_id) + { + unsigned long usable_links = ieee80211_vif_usable_links(vif); + int primary_link = iwl_mvm_mld_get_primary_link(mvm, vif, +@@ -418,7 +402,7 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm, + return; + } + +- iwl_mvm_bt_coex_update_vif_esr(mvm, vif, link_id); ++ iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); + + if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2)) + min_ag_for_static_smps = BT_VERY_HIGH_TRAFFIC; +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index 8f4b063d6243e..7ed7444c98715 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -1564,6 +1564,17 @@ static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm, + IWL_STA_MULTICAST); + } + ++void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif) ++{ ++ lockdep_assert_held(&mvm->mutex); ++ ++ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) ++ return; ++ ++ INIT_DELAYED_WORK(&mvmvif->csa_work, ++ iwl_mvm_channel_switch_disconnect_wk); ++} ++ + static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -1574,6 +1585,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + + mutex_lock(&mvm->mutex); + ++ iwl_mvm_mac_init_mvmvif(mvm, mvmvif); ++ + mvmvif->mvm = mvm; + + /* the first link always points to the default one */ +@@ -1651,15 +1664,10 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + IEEE80211_VIF_SUPPORTS_CQM_RSSI; + } + +- if (vif->p2p || iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) < 5) +- vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW; +- + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) + mvm->p2p_device_vif = vif; + + iwl_mvm_tcm_add_vif(mvm, vif); +- INIT_DELAYED_WORK(&mvmvif->csa_work, +- iwl_mvm_channel_switch_disconnect_wk); + + if (vif->type == NL80211_IFTYPE_MONITOR) { + mvm->monitor_on = true; +@@ -1697,6 +1705,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) + { ++ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ++ + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { + /* + * Flush the ROC worker which will flush the OFFCHANNEL queue. +@@ -1705,6 +1715,8 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, + */ + flush_work(&mvm->roc_done_wk); + } ++ ++ cancel_delayed_work_sync(&mvmvif->csa_work); + } + + /* This function is doing the common part of removing the interface for +@@ -3792,6 +3804,24 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw, + return callbacks->update_sta(mvm, vif, sta); + } + ++static void iwl_mvm_bt_coex_update_vif_esr(struct iwl_mvm *mvm, ++ struct ieee80211_vif *vif) ++{ ++ unsigned long usable_links = ieee80211_vif_usable_links(vif); ++ u8 link_id; ++ ++ for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ struct ieee80211_bss_conf *link_conf = ++ link_conf_dereference_protected(vif, link_id); ++ ++ if (WARN_ON_ONCE(!link_conf)) ++ return; ++ ++ if (link_conf->chanreq.oper.chan->band == NL80211_BAND_2GHZ) ++ iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); ++ } ++} ++ + static int + iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, +@@ -3819,6 +3849,9 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm, + callbacks->mac_ctxt_changed(mvm, vif, false); + iwl_mvm_mei_host_associated(mvm, vif, mvm_sta); + ++ /* Calculate eSR mode due to BT coex */ ++ iwl_mvm_bt_coex_update_vif_esr(mvm, vif); ++ + /* when client is authorized (AP station marked as such), + * try to enable more links + */ +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +index 084314bf6f369..df183a79db4c8 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +@@ -14,6 +14,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, + + mutex_lock(&mvm->mutex); + ++ iwl_mvm_mac_init_mvmvif(mvm, mvmvif); ++ + mvmvif->mvm = mvm; + + /* Not much to do here. The stack will not allow interface +@@ -92,6 +94,9 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, + mvm->csme_vif = vif; + } + ++ if (vif->p2p || iwl_fw_lookup_cmd_ver(mvm->fw, PHY_CONTEXT_CMD, 1) < 5) ++ vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW; ++ + goto out_unlock; + + out_free_bf: +@@ -189,17 +194,13 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw, + mutex_unlock(&mvm->mutex); + } + +-static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif) ++static unsigned int iwl_mvm_mld_count_active_links(struct iwl_mvm_vif *mvmvif) + { + unsigned int n_active = 0; + int i; + + for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) { +- struct ieee80211_bss_conf *link_conf; +- +- link_conf = link_conf_dereference_protected(vif, i); +- if (link_conf && +- rcu_access_pointer(link_conf->chanctx_conf)) ++ if (mvmvif->link[i] && mvmvif->link[i]->phy_ctxt) + n_active++; + } + +@@ -245,18 +246,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, + { + u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; + struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; +- unsigned int n_active = iwl_mvm_mld_count_active_links(vif); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ++ unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif); + unsigned int link_id = link_conf->link_id; + int ret; + +- /* if the assigned one was not counted yet, count it now */ +- if (!rcu_access_pointer(link_conf->chanctx_conf)) +- n_active++; +- + if (WARN_ON_ONCE(!mvmvif->link[link_id])) + return -EINVAL; + ++ /* if the assigned one was not counted yet, count it now */ ++ if (!mvmvif->link[link_id]->phy_ctxt) ++ n_active++; ++ + /* mac parameters such as HE support can change at this stage + * For sta, need first to configure correct state from drv_sta_state + * and only after that update mac config. +@@ -296,13 +297,8 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, + * this needs the phy context assigned (and in FW?), and we cannot + * do it later because it needs to be initialized as soon as we're + * able to TX on the link, i.e. when active. +- * +- * Firmware restart isn't quite correct yet for MLO, but we don't +- * need to do it in that case anyway since it will happen from the +- * normal station state callback. + */ +- if (mvmvif->ap_sta && +- !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { ++ if (mvmvif->ap_sta) { + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); +@@ -416,7 +412,7 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, + + { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +- unsigned int n_active = iwl_mvm_mld_count_active_links(vif); ++ unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif); + unsigned int link_id = link_conf->link_id; + + /* shouldn't happen, but verify link_id is valid before accessing */ +@@ -608,10 +604,49 @@ struct iwl_mvm_link_sel_data { + bool active; + }; + +-static bool iwl_mvm_mld_valid_link_pair(struct iwl_mvm_link_sel_data *a, ++static bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, ++ struct iwl_mvm_link_sel_data *a, + struct iwl_mvm_link_sel_data *b) + { +- return a->band != b->band; ++ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ++ ++ if (a->band == b->band) ++ return false; ++ ++ /* BT Coex effects eSR mode only if one of the link is on LB */ ++ if (a->band == NL80211_BAND_2GHZ || b->band == NL80211_BAND_2GHZ) ++ return !(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX); ++ ++ return true; ++} ++ ++static u8 ++iwl_mvm_set_link_selection_data(struct ieee80211_vif *vif, ++ struct iwl_mvm_link_sel_data *data, ++ unsigned long usable_links) ++{ ++ u8 n_data = 0; ++ unsigned long link_id; ++ ++ rcu_read_lock(); ++ ++ for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ struct ieee80211_bss_conf *link_conf = ++ rcu_dereference(vif->link_conf[link_id]); ++ ++ if (WARN_ON_ONCE(!link_conf)) ++ continue; ++ ++ data[n_data].link_id = link_id; ++ data[n_data].band = link_conf->chanreq.oper.chan->band; ++ data[n_data].width = link_conf->chanreq.oper.width; ++ data[n_data].active = vif->active_links & BIT(link_id); ++ n_data++; ++ } ++ ++ rcu_read_unlock(); ++ ++ return n_data; + } + + void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +@@ -621,7 +656,7 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + unsigned long usable_links = ieee80211_vif_usable_links(vif); + u32 max_active_links = iwl_mvm_max_active_links(mvm, vif); + u16 new_active_links; +- u8 link_id, n_data = 0, i, j; ++ u8 n_data, i, j; + + if (!IWL_MVM_AUTO_EML_ENABLE) + return; +@@ -646,23 +681,7 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + if (hweight16(vif->active_links) == max_active_links) + return; + +- rcu_read_lock(); +- +- for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { +- struct ieee80211_bss_conf *link_conf = +- rcu_dereference(vif->link_conf[link_id]); +- +- if (WARN_ON_ONCE(!link_conf)) +- continue; +- +- data[n_data].link_id = link_id; +- data[n_data].band = link_conf->chanreq.oper.chan->band; +- data[n_data].width = link_conf->chanreq.oper.width; +- data[n_data].active = vif->active_links & BIT(link_id); +- n_data++; +- } +- +- rcu_read_unlock(); ++ n_data = iwl_mvm_set_link_selection_data(vif, data, usable_links); + + /* this is expected to be the current active link */ + if (n_data == 1) +@@ -686,7 +705,8 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + if (i == j) + continue; + +- if (iwl_mvm_mld_valid_link_pair(&data[i], &data[j])) ++ if (iwl_mvm_mld_valid_link_pair(vif, &data[i], ++ &data[j])) + break; + } + +@@ -702,7 +722,7 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + if (i == j) + continue; + +- if (iwl_mvm_mld_valid_link_pair(&data[i], ++ if (iwl_mvm_mld_valid_link_pair(vif, &data[i], + &data[j])) + break; + } +@@ -1264,6 +1284,33 @@ int iwl_mvm_mld_get_primary_link(struct iwl_mvm *mvm, + return data[1].link_id; + } + ++void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ++{ ++ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ++ bool enable = !mvmvif->esr_disable_reason; ++ int link_id; ++ ++ /* Nothing to do */ ++ if (mvmvif->esr_active == enable) ++ return; ++ ++ if (enable) { ++ /* Try to re-enable eSR */ ++ iwl_mvm_mld_select_links(mvm, vif, false); ++ return; ++ } ++ ++ /* ++ * Find the primary link, as we want to switch to it and drop the ++ * secondary one. ++ */ ++ link_id = iwl_mvm_mld_get_primary_link(mvm, vif, vif->active_links); ++ WARN_ON(link_id < 0); ++ ++ ieee80211_set_active_links_async(vif, ++ vif->active_links & BIT(link_id)); ++} ++ + /* + * This function receives a bitmap of usable links and check if we can enter + * eSR on those links. +@@ -1272,14 +1319,13 @@ static bool iwl_mvm_can_enter_esr(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + unsigned long desired_links) + { +- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); +- int primary_link = iwl_mvm_mld_get_primary_link(mvm, vif, +- desired_links); ++ u16 usable_links = ieee80211_vif_usable_links(vif); ++ struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS]; + const struct wiphy_iftype_ext_capab *ext_capa; +- bool ret = true; +- int link_id; ++ u8 n_data; + +- if (primary_link < 0) ++ if (!ieee80211_vif_is_mld(vif) || !vif->cfg.assoc || ++ hweight16(usable_links) <= 1) + return false; + + if (!(vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP)) +@@ -1291,26 +1337,13 @@ static bool iwl_mvm_can_enter_esr(struct iwl_mvm *mvm, + !(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP)) + return false; + +- for_each_set_bit(link_id, &desired_links, IEEE80211_MLD_MAX_NUM_LINKS) { +- struct ieee80211_bss_conf *link_conf = +- link_conf_dereference_protected(vif, link_id); +- +- if (WARN_ON_ONCE(!link_conf)) +- continue; ++ n_data = iwl_mvm_set_link_selection_data(vif, data, desired_links); + +- /* BT Coex effects eSR mode only if one of the link is on LB */ +- if (link_conf->chanreq.oper.chan->band != NL80211_BAND_2GHZ) +- continue; ++ if (n_data != 2) ++ return false; + +- ret = iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link_id, +- primary_link); +- // Mark eSR as disabled for the next time +- if (!ret) +- mvmvif->bt_coex_esr_disabled = true; +- break; +- } + +- return ret; ++ return iwl_mvm_mld_valid_link_pair(vif, &data[0], &data[1]); + } + + static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw, +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +index 23e64a757cfe8..36dc291d98dd6 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +@@ -9,7 +9,9 @@ + u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + int filter_link_id) + { ++ struct ieee80211_link_sta *link_sta; + struct iwl_mvm_sta *mvmsta; ++ struct ieee80211_vif *vif; + unsigned int link_id; + u32 result = 0; + +@@ -17,26 +19,27 @@ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + return 0; + + mvmsta = iwl_mvm_sta_from_mac80211(sta); ++ vif = mvmsta->vif; + + /* it's easy when the STA is not an MLD */ + if (!sta->valid_links) + return BIT(mvmsta->deflink.sta_id); + + /* but if it is an MLD, get the mask of all the FW STAs it has ... */ +- for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) { +- struct iwl_mvm_link_sta *link_sta; ++ for_each_sta_active_link(vif, sta, link_sta, link_id) { ++ struct iwl_mvm_link_sta *mvm_link_sta; + + /* unless we have a specific link in mind */ + if (filter_link_id >= 0 && link_id != filter_link_id) + continue; + +- link_sta = ++ mvm_link_sta = + rcu_dereference_check(mvmsta->link[link_id], + lockdep_is_held(&mvm->mutex)); +- if (!link_sta) ++ if (!mvm_link_sta) + continue; + +- result |= BIT(link_sta->sta_id); ++ result |= BIT(mvm_link_sta->sta_id); + } + + return result; +@@ -582,14 +585,14 @@ static int iwl_mvm_mld_alloc_sta_links(struct iwl_mvm *mvm, + struct ieee80211_sta *sta) + { + struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); ++ struct ieee80211_link_sta *link_sta; + unsigned int link_id; + int ret; + + lockdep_assert_held(&mvm->mutex); + +- for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) { +- if (!rcu_access_pointer(sta->link[link_id]) || +- mvm_sta->link[link_id]) ++ for_each_sta_active_link(vif, sta, link_sta, link_id) { ++ if (WARN_ON(mvm_sta->link[link_id])) + continue; + + ret = iwl_mvm_mld_alloc_sta_link(mvm, vif, sta, link_id); +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +index f0b24f00938bd..d1ab35eb55b23 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -346,6 +346,14 @@ struct iwl_mvm_vif_link_info { + u16 mgmt_queue; + }; + ++/** ++ * enum iwl_mvm_esr_disable_reason - reasons for which we can't enable EMLSR ++ * @IWL_MVM_ESR_DISABLE_COEX: COEX is preventing the enablement of EMLSR ++ */ ++enum iwl_mvm_esr_disable_reason { ++ IWL_MVM_ESR_DISABLE_COEX = BIT(0), ++}; ++ + /** + * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context + * @mvm: pointer back to the mvm struct +@@ -361,7 +369,6 @@ struct iwl_mvm_vif_link_info { + * @pm_enabled - indicate if MAC power management is allowed + * @monitor_active: indicates that monitor context is configured, and that the + * interface should get quota etc. +- * @bt_coex_esr_disabled: indicates if esr is disabled due to bt coex + * @low_latency: bit flags for low latency + * see enum &iwl_mvm_low_latency_cause for causes. + * @low_latency_actual: boolean, indicates low latency is set, +@@ -378,6 +385,7 @@ struct iwl_mvm_vif_link_info { + * @deflink: default link data for use in non-MLO + * @link: link data for each link in MLO + * @esr_active: indicates eSR mode is active ++ * @esr_disable_reason: a bitmap of enum iwl_mvm_esr_disable_reason + * @pm_enabled: indicates powersave is enabled + */ + struct iwl_mvm_vif { +@@ -392,7 +400,6 @@ struct iwl_mvm_vif { + bool pm_enabled; + bool monitor_active; + bool esr_active; +- bool bt_coex_esr_disabled; + + u8 low_latency: 6; + u8 low_latency_actual: 1; +@@ -400,6 +407,7 @@ struct iwl_mvm_vif { + u8 authorized:1; + bool ps_disabled; + ++ u32 esr_disable_reason; + u32 ap_beacon_time; + struct iwl_mvm_vif_bf_data bf_data; + +@@ -1572,15 +1580,14 @@ static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm, + struct iwl_trans *trans = mvm->fwrt.trans; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + +- lockdep_assert_held(&mvm->mutex); +- + if (vif->type == NL80211_IFTYPE_AP) + return mvm->fw->ucode_capa.num_beacons; + ++ /* Check if HW supports eSR or STR */ + if ((iwl_mvm_is_esr_supported(trans) && +- !mvmvif->bt_coex_esr_disabled) || +- ((CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM && +- CSR_HW_RFID_IS_CDB(trans->hw_rf_id)))) ++ !(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_DISABLE_COEX)) || ++ (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM && ++ CSR_HW_RFID_IS_CDB(trans->hw_rf_id))) + return IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM; + + return 1; +@@ -1776,6 +1783,8 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); + + int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm); + ++void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif); ++ + /* + * FW notifications / CMD responses handlers + * Convention: iwl_mvm_rx_<NAME OF THE CMD> +@@ -2133,12 +2142,9 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, + u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwl_mvm *mvm, u8 enabled_ants); + u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, + struct ieee80211_tx_info *info, u8 ac); +-bool iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, +- struct ieee80211_vif *vif, +- int link_id, int primary_link); +-void iwl_mvm_bt_coex_update_vif_esr(struct iwl_mvm *mvm, +- struct ieee80211_vif *vif, +- int link_id); ++void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm, ++ struct ieee80211_vif *vif, ++ int link_id); + + /* beacon filtering */ + #ifdef CONFIG_IWLWIFI_DEBUGFS +@@ -2779,4 +2785,8 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm, + struct ieee80211_channel *channel, + struct ieee80211_vif *vif, + int duration, u32 activity); ++ ++/* EMLSR */ ++void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif); ++ + #endif /* __IWL_MVM_H__ */ +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +index b1add7942c5bf..395aef04f691f 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +@@ -889,8 +889,8 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, + + if (link_info->phy_ctxt && + link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ) +- iwl_mvm_bt_coex_update_vif_esr(mvm, bss_conf->vif, +- link_id); ++ iwl_mvm_bt_coex_update_link_esr(mvm, bss_conf->vif, ++ link_id); + + /* make sure that beacon statistics don't go backwards with TCM + * request to clear statistics +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +index 11559563ae381..22bc032cffc8b 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +@@ -3171,8 +3171,13 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, + struct iwl_mvm_vif_link_info *link_info = + scan_vif->link[mvm->scan_link_id]; + +- if (!WARN_ON(!link_info)) ++ /* It is possible that by the time the scan is complete the link ++ * was already removed and is not valid. ++ */ ++ if (link_info) + memcpy(info.tsf_bssid, link_info->bssid, ETH_ALEN); ++ else ++ IWL_DEBUG_SCAN(mvm, "Scan link is no longer valid\n"); + + ieee80211_scan_completed(mvm->hw, &info); + mvm->scan_vif = NULL; +diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c +index ce8fea76dbb24..7a4ef5c83be48 100644 +--- a/drivers/net/wireless/marvell/mwl8k.c ++++ b/drivers/net/wireless/marvell/mwl8k.c +@@ -2718,7 +2718,7 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, + cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); + cmd->numaddr = cpu_to_le16(mc_count); + netdev_hw_addr_list_for_each(ha, mc_list) { +- memcpy(cmd->addr[i], ha->addr, ETH_ALEN); ++ memcpy(cmd->addr[i++], ha->addr, ETH_ALEN); + } + } + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +index 7a2f5d38562b4..14304b0637158 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +@@ -4,6 +4,13 @@ + #include "mac.h" + #include "../dma.h" + ++static const u8 wmm_queue_map[] = { ++ [IEEE80211_AC_BK] = 0, ++ [IEEE80211_AC_BE] = 1, ++ [IEEE80211_AC_VI] = 2, ++ [IEEE80211_AC_VO] = 3, ++}; ++ + static void + mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) + { +@@ -22,10 +29,10 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) + struct ieee80211_sta *sta; + struct mt7603_sta *msta; + struct mt76_wcid *wcid; ++ u8 tid = 0, hwq = 0; + void *priv; + int idx; + u32 val; +- u8 tid = 0; + + if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr)) + goto free; +@@ -42,19 +49,36 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) + goto free; + + priv = msta = container_of(wcid, struct mt7603_sta, wcid); +- val = le32_to_cpu(txd[0]); +- val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); +- val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT); +- txd[0] = cpu_to_le32(val); + + sta = container_of(priv, struct ieee80211_sta, drv_priv); + hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE]; +- if (ieee80211_is_data_qos(hdr->frame_control)) ++ ++ hwq = wmm_queue_map[IEEE80211_AC_BE]; ++ if (ieee80211_is_data_qos(hdr->frame_control)) { + tid = *ieee80211_get_qos_ctl(hdr) & +- IEEE80211_QOS_CTL_TAG1D_MASK; +- skb_set_queue_mapping(skb, tid_to_ac[tid]); ++ IEEE80211_QOS_CTL_TAG1D_MASK; ++ u8 qid = tid_to_ac[tid]; ++ hwq = wmm_queue_map[qid]; ++ skb_set_queue_mapping(skb, qid); ++ } else if (ieee80211_is_data(hdr->frame_control)) { ++ skb_set_queue_mapping(skb, IEEE80211_AC_BE); ++ hwq = wmm_queue_map[IEEE80211_AC_BE]; ++ } else { ++ skb_pull(skb, MT_TXD_SIZE); ++ if (!ieee80211_is_bufferable_mmpdu(skb)) ++ goto free; ++ skb_push(skb, MT_TXD_SIZE); ++ skb_set_queue_mapping(skb, MT_TXQ_PSD); ++ hwq = MT_TX_HW_QUEUE_MGMT; ++ } ++ + ieee80211_sta_set_buffered(sta, tid, true); + ++ val = le32_to_cpu(txd[0]); ++ val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); ++ val |= FIELD_PREP(MT_TXD0_Q_IDX, hwq); ++ txd[0] = cpu_to_le32(val); ++ + spin_lock_bh(&dev->ps_lock); + __skb_queue_tail(&msta->psq, skb); + if (skb_queue_len(&msta->psq) >= 64) { +@@ -151,12 +175,6 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget) + + int mt7603_dma_init(struct mt7603_dev *dev) + { +- static const u8 wmm_queue_map[] = { +- [IEEE80211_AC_BK] = 0, +- [IEEE80211_AC_BE] = 1, +- [IEEE80211_AC_VI] = 2, +- [IEEE80211_AC_VO] = 3, +- }; + int ret; + int i; + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +index cf21d06257e53..dc8a77f0a1cc4 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +@@ -1393,6 +1393,7 @@ void mt7603_pse_client_reset(struct mt7603_dev *dev) + MT_CLIENT_RESET_TX_R_E_2_S); + + /* Start PSE client TX abort */ ++ mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF); + mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1); + mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S, + MT_CLIENT_RESET_TX_R_E_1_S, 500); +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index af0c2b2aacb00..fb8bd50eb7de8 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -283,7 +283,7 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif, + }; + struct sk_buff *skb; + +- if (is_mt799x(dev) && !wcid->sta) ++ if (wcid && !wcid->sta) + hdr.muar_idx = 0xe; + + mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo, +@@ -2527,6 +2527,7 @@ int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend) + __le16 tag; + __le16 len; + u8 suspend; ++ u8 pad[7]; + } __packed hif_suspend; + } req = { + .hif_suspend = { +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +index 6c3696c8c7002..450f4d221184b 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +@@ -1049,6 +1049,7 @@ static ssize_t + mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) + { ++ int i, ret, pwr, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0; + struct mt7915_phy *phy = file->private_data; + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; +@@ -1057,7 +1058,6 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, + .band_idx = phy->mt76->band_idx, + }; + char buf[100]; +- int i, ret, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0; + enum mac80211_rx_encoding mode; + u32 offs = 0, len = 0; + +@@ -1130,8 +1130,8 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf, + if (ret) + goto out; + +- mphy->txpower_cur = max(mphy->txpower_cur, +- max(pwr160, max(pwr80, max(pwr40, pwr20)))); ++ pwr = max3(pwr80, pwr40, pwr20); ++ mphy->txpower_cur = max3(mphy->txpower_cur, pwr160, pwr); + out: + mutex_unlock(&dev->mt76.mutex); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h +index 2a0bbfe7bfa5e..b8315a89f4a9a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h +@@ -535,7 +535,7 @@ struct mt7925_wow_pattern_tlv { + u8 offset; + u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN]; + u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN]; +- u8 rsv[4]; ++ u8 rsv[7]; + } __packed; + + static inline enum connac3_mcu_cipher_type +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index b44abe2acc81b..e86c05d0eecc9 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -3729,6 +3729,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy) + } __packed * res; + struct sk_buff *skb; + int ret; ++ u32 temp; + + ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL), + &req, sizeof(req), true, &skb); +@@ -3736,8 +3737,10 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy) + return ret; + + res = (void *)skb->data; ++ temp = le32_to_cpu(res->temperature); ++ dev_kfree_skb(skb); + +- return le32_to_cpu(res->temperature); ++ return temp; + } + + int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state) +@@ -4464,7 +4467,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) + u8 band_idx; + } __packed req = { + .tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL), +- .len = cpu_to_le16(sizeof(req) + MT7996_SKU_RATE_NUM - 4), ++ .len = cpu_to_le16(sizeof(req) + MT7996_SKU_PATH_NUM - 4), + .power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL, + .power_limit_type = TX_POWER_LIMIT_TABLE_RATE, + .band_idx = phy->mt76->band_idx, +@@ -4479,7 +4482,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) + mphy->txpower_cur = tx_power; + + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, +- sizeof(req) + MT7996_SKU_RATE_NUM); ++ sizeof(req) + MT7996_SKU_PATH_NUM); + if (!skb) + return -ENOMEM; + +@@ -4503,6 +4506,9 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) + /* eht */ + skb_put_data(skb, &la.eht[0], sizeof(la.eht)); + ++ /* padding */ ++ skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM); ++ + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WM_UNI_CMD(TXPOWER), true); + } +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +index 304e5fd148034..928a9663b49e0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c +@@ -519,7 +519,7 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t) + struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet); + struct mtk_wed_device *wed = &dev->mt76.mmio.wed; + struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2; +- u32 i, intr, mask, intr1; ++ u32 i, intr, mask, intr1 = 0; + + if (dev->hif2 && mtk_wed_device_active(wed_hif2)) { + mtk_wed_device_irq_set_mask(wed_hif2, 0); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +index 36d1f247d55aa..ddeb40d522c5a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +@@ -50,6 +50,7 @@ + #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ + + #define MT7996_SKU_RATE_NUM 417 ++#define MT7996_SKU_PATH_NUM 494 + + #define MT7996_MAX_TWT_AGRT 16 + #define MT7996_MAX_STA_TWT_AGRT 8 +diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c +index 31290d8cb7f7c..92074b73ebebd 100644 +--- a/drivers/net/wireless/realtek/rtw89/ps.c ++++ b/drivers/net/wireless/realtek/rtw89/ps.c +@@ -55,7 +55,8 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev, + + static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter) + { +- if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode)) ++ if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) && ++ !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) + rtw89_ps_power_mode_change_with_hci(rtwdev, enter); + else + rtw89_mac_power_mode_change(rtwdev, enter); +diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c +index ccad026defb50..ca4835008b56e 100644 +--- a/drivers/net/wireless/realtek/rtw89/wow.c ++++ b/drivers/net/wireless/realtek/rtw89/wow.c +@@ -457,14 +457,17 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; + struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; ++ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool include_bb = !!chip->bbmcu_nr; ++ bool disable_intr_for_dlfw = false; + struct ieee80211_sta *wow_sta; + struct rtw89_sta *rtwsta = NULL; + bool is_conn = true; + int ret; + +- rtw89_hci_disable_intr(rtwdev); ++ if (chip_id == RTL8852C || chip_id == RTL8922A) ++ disable_intr_for_dlfw = true; + + wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); + if (wow_sta) +@@ -472,12 +475,18 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + else + is_conn = false; + ++ if (disable_intr_for_dlfw) ++ rtw89_hci_disable_intr(rtwdev); ++ + ret = rtw89_fw_download(rtwdev, fw_type, include_bb); + if (ret) { + rtw89_warn(rtwdev, "download fw failed\n"); + return ret; + } + ++ if (disable_intr_for_dlfw) ++ rtw89_hci_enable_intr(rtwdev); ++ + rtw89_phy_init_rf_reg(rtwdev, true); + + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, +@@ -520,7 +529,6 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) + } + + rtw89_mac_hw_mgnt_sec(rtwdev, wow); +- rtw89_hci_enable_intr(rtwdev); + + return 0; + } +diff --git a/drivers/of/module.c b/drivers/of/module.c +index f58e624953a20..780fd82a7ecc5 100644 +--- a/drivers/of/module.c ++++ b/drivers/of/module.c +@@ -29,14 +29,15 @@ ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len) + csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T', + of_node_get_device_type(np)); + tsize = csize; ++ if (csize >= len) ++ csize = len > 0 ? len - 1 : 0; + len -= csize; +- if (str) +- str += csize; ++ str += csize; + + of_property_for_each_string(np, "compatible", p, compat) { + csize = strlen(compat) + 1; + tsize += csize; +- if (csize > len) ++ if (csize >= len) + continue; + + csize = snprintf(str, len, "C%s", compat); +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +index 5d1f0e9fdb08d..dba3991256586 100644 +--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -350,15 +350,27 @@ static bool hisi_pcie_pmu_validate_event_group(struct perf_event *event) + return false; + + for (num = 0; num < counters; num++) { ++ /* ++ * If we find a related event, then it's a valid group ++ * since we don't need to allocate a new counter for it. ++ */ + if (hisi_pcie_pmu_cmp_event(event_group[num], sibling)) + break; + } + ++ /* ++ * Otherwise it's a new event but if there's no available counter, ++ * fail the check since we cannot schedule all the events in ++ * the group simultaneously. ++ */ ++ if (num == HISI_PCIE_MAX_COUNTERS) ++ return false; ++ + if (num == counters) + event_group[counters++] = sibling; + } + +- return counters <= HISI_PCIE_MAX_COUNTERS; ++ return true; + } + + static int hisi_pcie_pmu_event_init(struct perf_event *event) +diff --git a/drivers/perf/hisilicon/hns3_pmu.c b/drivers/perf/hisilicon/hns3_pmu.c +index 16869bf5bf4cc..60062eaa342aa 100644 +--- a/drivers/perf/hisilicon/hns3_pmu.c ++++ b/drivers/perf/hisilicon/hns3_pmu.c +@@ -1085,15 +1085,27 @@ static bool hns3_pmu_validate_event_group(struct perf_event *event) + return false; + + for (num = 0; num < counters; num++) { ++ /* ++ * If we find a related event, then it's a valid group ++ * since we don't need to allocate a new counter for it. ++ */ + if (hns3_pmu_cmp_event(event_group[num], sibling)) + break; + } + ++ /* ++ * Otherwise it's a new event but if there's no available counter, ++ * fail the check since we cannot schedule all the events in ++ * the group simultaneously. ++ */ ++ if (num == HNS3_PMU_MAX_HW_EVENTS) ++ return false; ++ + if (num == counters) + event_group[counters++] = sibling; + } + +- return counters <= HNS3_PMU_MAX_HW_EVENTS; ++ return true; + } + + static u32 hns3_pmu_get_filter_condition(struct perf_event *event) +@@ -1515,7 +1527,7 @@ static int hns3_pmu_irq_register(struct pci_dev *pdev, + return ret; + } + +- ret = devm_add_action(&pdev->dev, hns3_pmu_free_irq, pdev); ++ ret = devm_add_action_or_reset(&pdev->dev, hns3_pmu_free_irq, pdev); + if (ret) { + pci_err(pdev, "failed to add free irq action, ret = %d.\n", ret); + return ret; +diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c +index 8cbe6e5f9c39a..3e44d2fb8bf81 100644 +--- a/drivers/perf/riscv_pmu_sbi.c ++++ b/drivers/perf/riscv_pmu_sbi.c +@@ -27,7 +27,7 @@ + + #define ALT_SBI_PMU_OVERFLOW(__ovl) \ + asm volatile(ALTERNATIVE_2( \ +- "csrr %0, " __stringify(CSR_SSCOUNTOVF), \ ++ "csrr %0, " __stringify(CSR_SCOUNTOVF), \ + "csrr %0, " __stringify(THEAD_C9XX_CSR_SCOUNTEROF), \ + THEAD_VENDOR_ID, ERRATA_THEAD_PMU, \ + CONFIG_ERRATA_THEAD_PMU, \ +diff --git a/drivers/platform/x86/xiaomi-wmi.c b/drivers/platform/x86/xiaomi-wmi.c +index 54a2546bb93bf..be80f0bda9484 100644 +--- a/drivers/platform/x86/xiaomi-wmi.c ++++ b/drivers/platform/x86/xiaomi-wmi.c +@@ -2,8 +2,10 @@ + /* WMI driver for Xiaomi Laptops */ + + #include <linux/acpi.h> ++#include <linux/device.h> + #include <linux/input.h> + #include <linux/module.h> ++#include <linux/mutex.h> + #include <linux/wmi.h> + + #include <uapi/linux/input-event-codes.h> +@@ -20,12 +22,21 @@ + + struct xiaomi_wmi { + struct input_dev *input_dev; ++ struct mutex key_lock; /* Protects the key event sequence */ + unsigned int key_code; + }; + ++static void xiaomi_mutex_destroy(void *data) ++{ ++ struct mutex *lock = data; ++ ++ mutex_destroy(lock); ++} ++ + static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context) + { + struct xiaomi_wmi *data; ++ int ret; + + if (wdev == NULL || context == NULL) + return -EINVAL; +@@ -35,6 +46,11 @@ static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context) + return -ENOMEM; + dev_set_drvdata(&wdev->dev, data); + ++ mutex_init(&data->key_lock); ++ ret = devm_add_action_or_reset(&wdev->dev, xiaomi_mutex_destroy, &data->key_lock); ++ if (ret < 0) ++ return ret; ++ + data->input_dev = devm_input_allocate_device(&wdev->dev); + if (data->input_dev == NULL) + return -ENOMEM; +@@ -59,10 +75,12 @@ static void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) + if (data == NULL) + return; + ++ mutex_lock(&data->key_lock); + input_report_key(data->input_dev, data->key_code, 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, data->key_code, 0); + input_sync(data->input_dev); ++ mutex_unlock(&data->key_lock); + } + + static const struct wmi_device_id xiaomi_wmi_id_table[] = { +diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c +index 0d2c3724d0bc0..b86e11bdc07ef 100644 +--- a/drivers/power/supply/power_supply_sysfs.c ++++ b/drivers/power/supply/power_supply_sysfs.c +@@ -271,23 +271,6 @@ static ssize_t power_supply_show_usb_type(struct device *dev, + return count; + } + +-static ssize_t power_supply_show_charge_behaviour(struct device *dev, +- struct power_supply *psy, +- union power_supply_propval *value, +- char *buf) +-{ +- int ret; +- +- ret = power_supply_get_property(psy, +- POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, +- value); +- if (ret < 0) +- return ret; +- +- return power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours, +- value->intval, buf); +-} +- + static ssize_t power_supply_show_property(struct device *dev, + struct device_attribute *attr, + char *buf) { +@@ -321,7 +304,8 @@ static ssize_t power_supply_show_property(struct device *dev, + &value, buf); + break; + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: +- ret = power_supply_show_charge_behaviour(dev, psy, &value, buf); ++ ret = power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours, ++ value.intval, buf); + break; + case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER: + ret = sysfs_emit(buf, "%s\n", value.strval); +diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c +index 6506cfb89aa94..ee2ced88ab34f 100644 +--- a/drivers/ptp/ptp_ocp.c ++++ b/drivers/ptp/ptp_ocp.c +@@ -4562,7 +4562,7 @@ static int ptp_ocp_dpll_direction_set(const struct dpll_pin *pin, + return -EOPNOTSUPP; + mode = direction == DPLL_PIN_DIRECTION_INPUT ? + SMA_MODE_IN : SMA_MODE_OUT; +- return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr); ++ return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr + 1); + } + + static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin, +@@ -4583,7 +4583,7 @@ static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin, + tbl = bp->sma_op->tbl[sma->mode]; + for (i = 0; tbl[i].name; i++) + if (tbl[i].frequency == frequency) +- return ptp_ocp_sma_store_val(bp, i, sma->mode, sma_nr); ++ return ptp_ocp_sma_store_val(bp, i, sma->mode, sma_nr + 1); + return -EINVAL; + } + +@@ -4600,7 +4600,7 @@ static int ptp_ocp_dpll_frequency_get(const struct dpll_pin *pin, + u32 val; + int i; + +- val = bp->sma_op->get(bp, sma_nr); ++ val = bp->sma_op->get(bp, sma_nr + 1); + tbl = bp->sma_op->tbl[sma->mode]; + for (i = 0; tbl[i].name; i++) + if (val == tbl[i].value) { +diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c +index a02fdbc612562..e12b6ff70baba 100644 +--- a/drivers/pwm/pwm-meson.c ++++ b/drivers/pwm/pwm-meson.c +@@ -147,7 +147,7 @@ static int meson_pwm_calc(struct pwm_chip *chip, struct pwm_device *pwm, + struct meson_pwm *meson = to_meson_pwm(chip); + struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; + unsigned int cnt, duty_cnt; +- unsigned long fin_freq; ++ long fin_freq; + u64 duty, period, freq; + + duty = state->duty_cycle; +@@ -167,14 +167,15 @@ static int meson_pwm_calc(struct pwm_chip *chip, struct pwm_device *pwm, + freq = ULONG_MAX; + + fin_freq = clk_round_rate(channel->clk, freq); +- if (fin_freq == 0) { +- dev_err(pwmchip_parent(chip), "invalid source clock frequency\n"); +- return -EINVAL; ++ if (fin_freq <= 0) { ++ dev_err(pwmchip_parent(chip), ++ "invalid source clock frequency %llu\n", freq); ++ return fin_freq ? fin_freq : -EINVAL; + } + +- dev_dbg(pwmchip_parent(chip), "fin_freq: %lu Hz\n", fin_freq); ++ dev_dbg(pwmchip_parent(chip), "fin_freq: %ld Hz\n", fin_freq); + +- cnt = div_u64(fin_freq * period, NSEC_PER_SEC); ++ cnt = mul_u64_u64_div_u64(fin_freq, period, NSEC_PER_SEC); + if (cnt > 0xffff) { + dev_err(pwmchip_parent(chip), "unable to get period cnt\n"); + return -EINVAL; +@@ -189,7 +190,7 @@ static int meson_pwm_calc(struct pwm_chip *chip, struct pwm_device *pwm, + channel->hi = 0; + channel->lo = cnt; + } else { +- duty_cnt = div_u64(fin_freq * duty, NSEC_PER_SEC); ++ duty_cnt = mul_u64_u64_div_u64(fin_freq, duty, NSEC_PER_SEC); + + dev_dbg(pwmchip_parent(chip), "duty=%llu duty_cnt=%u\n", duty, duty_cnt); + +diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c +index 39d80da0e14af..f07b1126e7a81 100644 +--- a/drivers/pwm/pwm-sti.c ++++ b/drivers/pwm/pwm-sti.c +@@ -624,32 +624,20 @@ static int sti_pwm_probe(struct platform_device *pdev) + return ret; + + if (cdata->pwm_num_devs) { +- pc->pwm_clk = of_clk_get_by_name(dev->of_node, "pwm"); ++ pc->pwm_clk = devm_clk_get_prepared(dev, "pwm"); + if (IS_ERR(pc->pwm_clk)) { + dev_err(dev, "failed to get PWM clock\n"); + return PTR_ERR(pc->pwm_clk); + } +- +- ret = clk_prepare(pc->pwm_clk); +- if (ret) { +- dev_err(dev, "failed to prepare clock\n"); +- return ret; +- } + } + + if (cdata->cpt_num_devs) { +- pc->cpt_clk = of_clk_get_by_name(dev->of_node, "capture"); ++ pc->cpt_clk = devm_clk_get_prepared(dev, "capture"); + if (IS_ERR(pc->cpt_clk)) { + dev_err(dev, "failed to get PWM capture clock\n"); + return PTR_ERR(pc->cpt_clk); + } + +- ret = clk_prepare(pc->cpt_clk); +- if (ret) { +- dev_err(dev, "failed to prepare clock\n"); +- return ret; +- } +- + cdata->ddata = devm_kzalloc(dev, cdata->cpt_num_devs * sizeof(*cdata->ddata), GFP_KERNEL); + if (!cdata->ddata) + return -ENOMEM; +@@ -664,27 +652,7 @@ static int sti_pwm_probe(struct platform_device *pdev) + mutex_init(&ddata->lock); + } + +- ret = pwmchip_add(chip); +- if (ret < 0) { +- clk_unprepare(pc->pwm_clk); +- clk_unprepare(pc->cpt_clk); +- return ret; +- } +- +- platform_set_drvdata(pdev, chip); +- +- return 0; +-} +- +-static void sti_pwm_remove(struct platform_device *pdev) +-{ +- struct pwm_chip *chip = platform_get_drvdata(pdev); +- struct sti_pwm_chip *pc = to_sti_pwmchip(chip); +- +- pwmchip_remove(chip); +- +- clk_unprepare(pc->pwm_clk); +- clk_unprepare(pc->cpt_clk); ++ return devm_pwmchip_add(dev, chip); + } + + static const struct of_device_id sti_pwm_of_match[] = { +@@ -699,7 +667,6 @@ static struct platform_driver sti_pwm_driver = { + .of_match_table = sti_pwm_of_match, + }, + .probe = sti_pwm_probe, +- .remove_new = sti_pwm_remove, + }; + module_platform_driver(sti_pwm_driver); + +diff --git a/drivers/s390/cio/trace.h b/drivers/s390/cio/trace.h +index 86993de253451..a4c5c6736b310 100644 +--- a/drivers/s390/cio/trace.h ++++ b/drivers/s390/cio/trace.h +@@ -50,7 +50,7 @@ DECLARE_EVENT_CLASS(s390_class_schib, + __entry->devno = schib->pmcw.dev; + __entry->schib = *schib; + __entry->pmcw_ena = schib->pmcw.ena; +- __entry->pmcw_st = schib->pmcw.ena; ++ __entry->pmcw_st = schib->pmcw.st; + __entry->pmcw_dnv = schib->pmcw.dnv; + __entry->pmcw_dev = schib->pmcw.dev; + __entry->pmcw_lpm = schib->pmcw.lpm; +diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c +index 52db147d9979d..f6dd077d47c9a 100644 +--- a/drivers/scsi/bfa/bfad_debugfs.c ++++ b/drivers/scsi/bfa/bfad_debugfs.c +@@ -250,7 +250,7 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf, + unsigned long flags; + void *kern_buf; + +- kern_buf = memdup_user(buf, nbytes); ++ kern_buf = memdup_user_nul(buf, nbytes); + if (IS_ERR(kern_buf)) + return PTR_ERR(kern_buf); + +@@ -317,7 +317,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf, + unsigned long flags; + void *kern_buf; + +- kern_buf = memdup_user(buf, nbytes); ++ kern_buf = memdup_user_nul(buf, nbytes); + if (IS_ERR(kern_buf)) + return PTR_ERR(kern_buf); + +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index af18d20f30794..49c57a9c110b5 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -5850,7 +5850,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h) + { + struct Scsi_Host *sh; + +- sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info)); ++ sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info *)); + if (sh == NULL) { + dev_err(&h->pdev->dev, "scsi_host_alloc failed\n"); + return -ENOMEM; +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index f6e6db8b8aba9..e97f4e01a865a 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -239,8 +239,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, + /* help some expanders that fail to zero sas_address in the 'no + * device' case + */ +- if (phy->attached_dev_type == SAS_PHY_UNUSED || +- phy->linkrate < SAS_LINK_RATE_1_5_GBPS) ++ if (phy->attached_dev_type == SAS_PHY_UNUSED) + memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); + else + memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE); +diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c +index 451fd236bfd05..96174353e3898 100644 +--- a/drivers/scsi/qedf/qedf_debugfs.c ++++ b/drivers/scsi/qedf/qedf_debugfs.c +@@ -170,7 +170,7 @@ qedf_dbg_debug_cmd_write(struct file *filp, const char __user *buffer, + if (!count || *ppos) + return 0; + +- kern_buf = memdup_user(buffer, count); ++ kern_buf = memdup_user_nul(buffer, count); + if (IS_ERR(kern_buf)) + return PTR_ERR(kern_buf); + +diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c +index 55ff3d7482b3e..a1545dad0c0ce 100644 +--- a/drivers/scsi/qla2xxx/qla_dfs.c ++++ b/drivers/scsi/qla2xxx/qla_dfs.c +@@ -274,7 +274,7 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) + seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n", + iocbs_used, ha->base_qpair->fwres.iocbs_limit); + +- seq_printf(s, "estimate exchange used[%d] high water limit [%d] n", ++ seq_printf(s, "estimate exchange used[%d] high water limit [%d]\n", + exch_used, ha->base_qpair->fwres.exch_limit); + + if (ql2xenforce_iocb_limit == 2) { +diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c +index b0cd071c4719b..0b2e5690dacfa 100644 +--- a/drivers/soc/mediatek/mtk-cmdq-helper.c ++++ b/drivers/soc/mediatek/mtk-cmdq-helper.c +@@ -14,7 +14,8 @@ + #define CMDQ_POLL_ENABLE_MASK BIT(0) + #define CMDQ_EOC_IRQ_EN BIT(0) + #define CMDQ_REG_TYPE 1 +-#define CMDQ_JUMP_RELATIVE 1 ++#define CMDQ_JUMP_RELATIVE 0 ++#define CMDQ_JUMP_ABSOLUTE 1 + + struct cmdq_instruction { + union { +@@ -397,7 +398,7 @@ int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr) + struct cmdq_instruction inst = {}; + + inst.op = CMDQ_CODE_JUMP; +- inst.offset = CMDQ_JUMP_RELATIVE; ++ inst.offset = CMDQ_JUMP_ABSOLUTE; + inst.value = addr >> + cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan); + return cmdq_pkt_append_command(pkt, inst); +diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c +index f913e9bd57ed4..823fd108fa039 100644 +--- a/drivers/soc/qcom/pmic_glink.c ++++ b/drivers/soc/qcom/pmic_glink.c +@@ -11,6 +11,7 @@ + #include <linux/slab.h> + #include <linux/soc/qcom/pdr.h> + #include <linux/soc/qcom/pmic_glink.h> ++#include <linux/spinlock.h> + + enum { + PMIC_GLINK_CLIENT_BATT = 0, +@@ -36,7 +37,7 @@ struct pmic_glink { + unsigned int pdr_state; + + /* serializing clients list updates */ +- struct mutex client_lock; ++ spinlock_t client_lock; + struct list_head clients; + }; + +@@ -58,10 +59,11 @@ static void _devm_pmic_glink_release_client(struct device *dev, void *res) + { + struct pmic_glink_client *client = (struct pmic_glink_client *)res; + struct pmic_glink *pg = client->pg; ++ unsigned long flags; + +- mutex_lock(&pg->client_lock); ++ spin_lock_irqsave(&pg->client_lock, flags); + list_del(&client->node); +- mutex_unlock(&pg->client_lock); ++ spin_unlock_irqrestore(&pg->client_lock, flags); + } + + struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev, +@@ -72,6 +74,7 @@ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev, + { + struct pmic_glink_client *client; + struct pmic_glink *pg = dev_get_drvdata(dev->parent); ++ unsigned long flags; + + client = devres_alloc(_devm_pmic_glink_release_client, sizeof(*client), GFP_KERNEL); + if (!client) +@@ -83,9 +86,14 @@ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev, + client->pdr_notify = pdr; + client->priv = priv; + +- mutex_lock(&pg->client_lock); ++ mutex_lock(&pg->state_lock); ++ spin_lock_irqsave(&pg->client_lock, flags); ++ + list_add(&client->node, &pg->clients); +- mutex_unlock(&pg->client_lock); ++ client->pdr_notify(client->priv, pg->client_state); ++ ++ spin_unlock_irqrestore(&pg->client_lock, flags); ++ mutex_unlock(&pg->state_lock); + + devres_add(dev, client); + +@@ -107,6 +115,7 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data, + struct pmic_glink_client *client; + struct pmic_glink_hdr *hdr; + struct pmic_glink *pg = dev_get_drvdata(&rpdev->dev); ++ unsigned long flags; + + if (len < sizeof(*hdr)) { + dev_warn(pg->dev, "ignoring truncated message\n"); +@@ -115,10 +124,12 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data, + + hdr = data; + ++ spin_lock_irqsave(&pg->client_lock, flags); + list_for_each_entry(client, &pg->clients, node) { + if (client->id == le32_to_cpu(hdr->owner)) + client->cb(data, len, client->priv); + } ++ spin_unlock_irqrestore(&pg->client_lock, flags); + + return 0; + } +@@ -158,6 +169,7 @@ static void pmic_glink_state_notify_clients(struct pmic_glink *pg) + { + struct pmic_glink_client *client; + unsigned int new_state = pg->client_state; ++ unsigned long flags; + + if (pg->client_state != SERVREG_SERVICE_STATE_UP) { + if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept) +@@ -168,8 +180,10 @@ static void pmic_glink_state_notify_clients(struct pmic_glink *pg) + } + + if (new_state != pg->client_state) { ++ spin_lock_irqsave(&pg->client_lock, flags); + list_for_each_entry(client, &pg->clients, node) + client->pdr_notify(client->priv, new_state); ++ spin_unlock_irqrestore(&pg->client_lock, flags); + pg->client_state = new_state; + } + } +@@ -256,7 +270,7 @@ static int pmic_glink_probe(struct platform_device *pdev) + pg->dev = &pdev->dev; + + INIT_LIST_HEAD(&pg->clients); +- mutex_init(&pg->client_lock); ++ spin_lock_init(&pg->client_lock); + mutex_init(&pg->state_lock); + + match_data = (unsigned long *)of_device_get_match_data(&pdev->dev); +diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c +index 938a4ea89c590..8c30191b21a77 100644 +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -4690,6 +4690,7 @@ static int load_video_binaries(struct ia_css_pipe *pipe) + sizeof(struct ia_css_binary), + GFP_KERNEL); + if (!mycs->yuv_scaler_binary) { ++ mycs->num_yuv_scaler = 0; + err = -ENOMEM; + return err; + } +diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c +index a587f860101ae..323aa70fdeaf1 100644 +--- a/drivers/staging/media/starfive/camss/stf-camss.c ++++ b/drivers/staging/media/starfive/camss/stf-camss.c +@@ -162,6 +162,12 @@ static int stfcamss_register_devs(struct stfcamss *stfcamss) + + static void stfcamss_unregister_devs(struct stfcamss *stfcamss) + { ++ struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV]; ++ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev; ++ ++ media_entity_remove_links(&isp_dev->subdev.entity); ++ media_entity_remove_links(&cap_yuv->video.vdev.entity); ++ + stf_isp_unregister(&stfcamss->isp_dev); + stf_capture_unregister(stfcamss); + } +diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c +index fd4bd650c77a6..4e5c213a89225 100644 +--- a/drivers/thermal/mediatek/lvts_thermal.c ++++ b/drivers/thermal/mediatek/lvts_thermal.c +@@ -1530,11 +1530,15 @@ static const struct lvts_data mt7988_lvts_ap_data = { + static const struct lvts_data mt8192_lvts_mcu_data = { + .lvts_ctrl = mt8192_lvts_mcu_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), ++ .temp_factor = LVTS_COEFF_A_MT8195, ++ .temp_offset = LVTS_COEFF_B_MT8195, + }; + + static const struct lvts_data mt8192_lvts_ap_data = { + .lvts_ctrl = mt8192_lvts_ap_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl), ++ .temp_factor = LVTS_COEFF_A_MT8195, ++ .temp_offset = LVTS_COEFF_B_MT8195, + }; + + static const struct lvts_data mt8195_lvts_mcu_data = { +diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c +index 6d7c16ccb44dc..4edee8d929a75 100644 +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -264,7 +264,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, + for (i = 0; i < priv->num_sensors; i++) { + dev_dbg(priv->dev, + "%s: sensor%d - data_point1:%#x data_point2:%#x\n", +- __func__, i, p1[i], p2[i]); ++ __func__, i, p1[i], p2 ? p2[i] : 0); + + if (!priv->sensor[i].slope) + priv->sensor[i].slope = SLOPE_DEFAULT; +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 34a31bc720230..38b7d02384d7c 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -431,7 +431,6 @@ static void update_temperature(struct thermal_zone_device *tz) + trace_thermal_temperature(tz); + + thermal_genl_sampling_temp(tz->id, temp); +- thermal_debug_update_temp(tz); + } + + static void thermal_zone_device_check(struct work_struct *work) +@@ -475,6 +474,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, + for_each_trip(tz, trip) + handle_thermal_trip(tz, trip); + ++ thermal_debug_update_temp(tz); ++ + monitor_thermal_zone(tz); + } + +@@ -897,6 +898,7 @@ __thermal_cooling_device_register(struct device_node *np, + { + struct thermal_cooling_device *cdev; + struct thermal_zone_device *pos = NULL; ++ unsigned long current_state; + int id, ret; + + if (!ops || !ops->get_max_state || !ops->get_cur_state || +@@ -934,6 +936,10 @@ __thermal_cooling_device_register(struct device_node *np, + if (ret) + goto out_cdev_type; + ++ ret = cdev->ops->get_cur_state(cdev, ¤t_state); ++ if (ret) ++ goto out_cdev_type; ++ + thermal_cooling_device_setup_sysfs(cdev); + + ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); +@@ -947,6 +953,8 @@ __thermal_cooling_device_register(struct device_node *np, + return ERR_PTR(ret); + } + ++ thermal_debug_cdev_add(cdev, current_state); ++ + /* Add 'this' new cdev to the global cdev list */ + mutex_lock(&thermal_list_lock); + +@@ -962,8 +970,6 @@ __thermal_cooling_device_register(struct device_node *np, + + mutex_unlock(&thermal_list_lock); + +- thermal_debug_cdev_add(cdev); +- + return cdev; + + out_cooling_dev: +diff --git a/drivers/thermal/thermal_debugfs.c b/drivers/thermal/thermal_debugfs.c +index 5693cc8b231aa..403f74d663dce 100644 +--- a/drivers/thermal/thermal_debugfs.c ++++ b/drivers/thermal/thermal_debugfs.c +@@ -435,6 +435,14 @@ void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev, + } + + cdev_dbg->current_state = new_state; ++ ++ /* ++ * Create a record for the new state if it is not there, so its ++ * duration will be printed by cdev_dt_seq_show() as expected if it ++ * runs before the next state transition. ++ */ ++ thermal_debugfs_cdev_record_get(thermal_dbg, cdev_dbg->durations, new_state); ++ + transition = (old_state << 16) | new_state; + + /* +@@ -460,8 +468,9 @@ void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev, + * Allocates a cooling device object for debug, initializes the + * statistics and create the entries in sysfs. + * @cdev: a pointer to a cooling device ++ * @state: current state of the cooling device + */ +-void thermal_debug_cdev_add(struct thermal_cooling_device *cdev) ++void thermal_debug_cdev_add(struct thermal_cooling_device *cdev, int state) + { + struct thermal_debugfs *thermal_dbg; + struct cdev_debugfs *cdev_dbg; +@@ -478,9 +487,16 @@ void thermal_debug_cdev_add(struct thermal_cooling_device *cdev) + INIT_LIST_HEAD(&cdev_dbg->durations[i]); + } + +- cdev_dbg->current_state = 0; ++ cdev_dbg->current_state = state; + cdev_dbg->timestamp = ktime_get(); + ++ /* ++ * Create a record for the initial cooling device state, so its ++ * duration will be printed by cdev_dt_seq_show() as expected if it ++ * runs before the first state transition. ++ */ ++ thermal_debugfs_cdev_record_get(thermal_dbg, cdev_dbg->durations, state); ++ + debugfs_create_file("trans_table", 0400, thermal_dbg->d_top, + thermal_dbg, &tt_fops); + +@@ -555,7 +571,6 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz, + struct tz_episode *tze; + struct tz_debugfs *tz_dbg; + struct thermal_debugfs *thermal_dbg = tz->debugfs; +- int temperature = tz->temperature; + int trip_id = thermal_zone_trip_id(tz, trip); + ktime_t now = ktime_get(); + +@@ -624,12 +639,6 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz, + + tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node); + tze->trip_stats[trip_id].timestamp = now; +- tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, temperature); +- tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, temperature); +- tze->trip_stats[trip_id].count++; +- tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg + +- (temperature - tze->trip_stats[trip_id].avg) / +- tze->trip_stats[trip_id].count; + + unlock: + mutex_unlock(&thermal_dbg->lock); +diff --git a/drivers/thermal/thermal_debugfs.h b/drivers/thermal/thermal_debugfs.h +index 155b9af5fe870..c28bd4c114124 100644 +--- a/drivers/thermal/thermal_debugfs.h ++++ b/drivers/thermal/thermal_debugfs.h +@@ -2,7 +2,7 @@ + + #ifdef CONFIG_THERMAL_DEBUGFS + void thermal_debug_init(void); +-void thermal_debug_cdev_add(struct thermal_cooling_device *cdev); ++void thermal_debug_cdev_add(struct thermal_cooling_device *cdev, int state); + void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev); + void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev, int state); + void thermal_debug_tz_add(struct thermal_zone_device *tz); +@@ -14,7 +14,7 @@ void thermal_debug_tz_trip_down(struct thermal_zone_device *tz, + void thermal_debug_update_temp(struct thermal_zone_device *tz); + #else + static inline void thermal_debug_init(void) {} +-static inline void thermal_debug_cdev_add(struct thermal_cooling_device *cdev) {} ++static inline void thermal_debug_cdev_add(struct thermal_cooling_device *cdev, int state) {} + static inline void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev) {} + static inline void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev, + int state) {} +diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c +index 4036566febcba..afbf7837b53ec 100644 +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -245,16 +245,18 @@ enum gsm_encoding { + + enum gsm_mux_state { + GSM_SEARCH, +- GSM_START, +- GSM_ADDRESS, +- GSM_CONTROL, +- GSM_LEN, +- GSM_DATA, +- GSM_FCS, +- GSM_OVERRUN, +- GSM_LEN0, +- GSM_LEN1, +- GSM_SSOF, ++ GSM0_ADDRESS, ++ GSM0_CONTROL, ++ GSM0_LEN0, ++ GSM0_LEN1, ++ GSM0_DATA, ++ GSM0_FCS, ++ GSM0_SSOF, ++ GSM1_START, ++ GSM1_ADDRESS, ++ GSM1_CONTROL, ++ GSM1_DATA, ++ GSM1_OVERRUN, + }; + + /* +@@ -2847,6 +2849,30 @@ static void gsm_queue(struct gsm_mux *gsm) + return; + } + ++/** ++ * gsm0_receive_state_check_and_fix - check and correct receive state ++ * @gsm: gsm data for this ldisc instance ++ * ++ * Ensures that the current receive state is valid for basic option mode. ++ */ ++ ++static void gsm0_receive_state_check_and_fix(struct gsm_mux *gsm) ++{ ++ switch (gsm->state) { ++ case GSM_SEARCH: ++ case GSM0_ADDRESS: ++ case GSM0_CONTROL: ++ case GSM0_LEN0: ++ case GSM0_LEN1: ++ case GSM0_DATA: ++ case GSM0_FCS: ++ case GSM0_SSOF: ++ break; ++ default: ++ gsm->state = GSM_SEARCH; ++ break; ++ } ++} + + /** + * gsm0_receive - perform processing for non-transparency +@@ -2860,26 +2886,27 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c) + { + unsigned int len; + ++ gsm0_receive_state_check_and_fix(gsm); + switch (gsm->state) { + case GSM_SEARCH: /* SOF marker */ + if (c == GSM0_SOF) { +- gsm->state = GSM_ADDRESS; ++ gsm->state = GSM0_ADDRESS; + gsm->address = 0; + gsm->len = 0; + gsm->fcs = INIT_FCS; + } + break; +- case GSM_ADDRESS: /* Address EA */ ++ case GSM0_ADDRESS: /* Address EA */ + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + if (gsm_read_ea(&gsm->address, c)) +- gsm->state = GSM_CONTROL; ++ gsm->state = GSM0_CONTROL; + break; +- case GSM_CONTROL: /* Control Byte */ ++ case GSM0_CONTROL: /* Control Byte */ + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + gsm->control = c; +- gsm->state = GSM_LEN0; ++ gsm->state = GSM0_LEN0; + break; +- case GSM_LEN0: /* Length EA */ ++ case GSM0_LEN0: /* Length EA */ + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + if (gsm_read_ea(&gsm->len, c)) { + if (gsm->len > gsm->mru) { +@@ -2889,14 +2916,14 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c) + } + gsm->count = 0; + if (!gsm->len) +- gsm->state = GSM_FCS; ++ gsm->state = GSM0_FCS; + else +- gsm->state = GSM_DATA; ++ gsm->state = GSM0_DATA; + break; + } +- gsm->state = GSM_LEN1; ++ gsm->state = GSM0_LEN1; + break; +- case GSM_LEN1: ++ case GSM0_LEN1: + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + len = c; + gsm->len |= len << 7; +@@ -2907,26 +2934,29 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c) + } + gsm->count = 0; + if (!gsm->len) +- gsm->state = GSM_FCS; ++ gsm->state = GSM0_FCS; + else +- gsm->state = GSM_DATA; ++ gsm->state = GSM0_DATA; + break; +- case GSM_DATA: /* Data */ ++ case GSM0_DATA: /* Data */ + gsm->buf[gsm->count++] = c; +- if (gsm->count == gsm->len) { ++ if (gsm->count >= MAX_MRU) { ++ gsm->bad_size++; ++ gsm->state = GSM_SEARCH; ++ } else if (gsm->count >= gsm->len) { + /* Calculate final FCS for UI frames over all data */ + if ((gsm->control & ~PF) != UIH) { + gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, + gsm->count); + } +- gsm->state = GSM_FCS; ++ gsm->state = GSM0_FCS; + } + break; +- case GSM_FCS: /* FCS follows the packet */ ++ case GSM0_FCS: /* FCS follows the packet */ + gsm->fcs = gsm_fcs_add(gsm->fcs, c); +- gsm->state = GSM_SSOF; ++ gsm->state = GSM0_SSOF; + break; +- case GSM_SSOF: ++ case GSM0_SSOF: + gsm->state = GSM_SEARCH; + if (c == GSM0_SOF) + gsm_queue(gsm); +@@ -2939,6 +2969,29 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c) + } + } + ++/** ++ * gsm1_receive_state_check_and_fix - check and correct receive state ++ * @gsm: gsm data for this ldisc instance ++ * ++ * Ensures that the current receive state is valid for advanced option mode. ++ */ ++ ++static void gsm1_receive_state_check_and_fix(struct gsm_mux *gsm) ++{ ++ switch (gsm->state) { ++ case GSM_SEARCH: ++ case GSM1_START: ++ case GSM1_ADDRESS: ++ case GSM1_CONTROL: ++ case GSM1_DATA: ++ case GSM1_OVERRUN: ++ break; ++ default: ++ gsm->state = GSM_SEARCH; ++ break; ++ } ++} ++ + /** + * gsm1_receive - perform processing for non-transparency + * @gsm: gsm data for this ldisc instance +@@ -2949,6 +3002,7 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c) + + static void gsm1_receive(struct gsm_mux *gsm, u8 c) + { ++ gsm1_receive_state_check_and_fix(gsm); + /* handle XON/XOFF */ + if ((c & ISO_IEC_646_MASK) == XON) { + gsm->constipated = true; +@@ -2961,11 +3015,11 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c) + } + if (c == GSM1_SOF) { + /* EOF is only valid in frame if we have got to the data state */ +- if (gsm->state == GSM_DATA) { ++ if (gsm->state == GSM1_DATA) { + if (gsm->count < 1) { + /* Missing FSC */ + gsm->malformed++; +- gsm->state = GSM_START; ++ gsm->state = GSM1_START; + return; + } + /* Remove the FCS from data */ +@@ -2981,14 +3035,14 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c) + gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->buf[gsm->count]); + gsm->len = gsm->count; + gsm_queue(gsm); +- gsm->state = GSM_START; ++ gsm->state = GSM1_START; + return; + } + /* Any partial frame was a runt so go back to start */ +- if (gsm->state != GSM_START) { ++ if (gsm->state != GSM1_START) { + if (gsm->state != GSM_SEARCH) + gsm->malformed++; +- gsm->state = GSM_START; ++ gsm->state = GSM1_START; + } + /* A SOF in GSM_START means we are still reading idling or + framing bytes */ +@@ -3009,30 +3063,30 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c) + gsm->escape = false; + } + switch (gsm->state) { +- case GSM_START: /* First byte after SOF */ ++ case GSM1_START: /* First byte after SOF */ + gsm->address = 0; +- gsm->state = GSM_ADDRESS; ++ gsm->state = GSM1_ADDRESS; + gsm->fcs = INIT_FCS; + fallthrough; +- case GSM_ADDRESS: /* Address continuation */ ++ case GSM1_ADDRESS: /* Address continuation */ + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + if (gsm_read_ea(&gsm->address, c)) +- gsm->state = GSM_CONTROL; ++ gsm->state = GSM1_CONTROL; + break; +- case GSM_CONTROL: /* Control Byte */ ++ case GSM1_CONTROL: /* Control Byte */ + gsm->fcs = gsm_fcs_add(gsm->fcs, c); + gsm->control = c; + gsm->count = 0; +- gsm->state = GSM_DATA; ++ gsm->state = GSM1_DATA; + break; +- case GSM_DATA: /* Data */ +- if (gsm->count > gsm->mru) { /* Allow one for the FCS */ +- gsm->state = GSM_OVERRUN; ++ case GSM1_DATA: /* Data */ ++ if (gsm->count > gsm->mru || gsm->count > MAX_MRU) { /* Allow one for the FCS */ ++ gsm->state = GSM1_OVERRUN; + gsm->bad_size++; + } else + gsm->buf[gsm->count++] = c; + break; +- case GSM_OVERRUN: /* Over-long - eg a dropped SOF */ ++ case GSM1_OVERRUN: /* Over-long - eg a dropped SOF */ + break; + default: + pr_debug("%s: unhandled state: %d\n", __func__, gsm->state); +diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c +index 5daa38d9c64e0..61d81b11f6a3d 100644 +--- a/drivers/tty/serial/8250/8250_bcm7271.c ++++ b/drivers/tty/serial/8250/8250_bcm7271.c +@@ -675,18 +675,46 @@ static void init_real_clk_rates(struct device *dev, struct brcmuart_priv *priv) + clk_set_rate(priv->baud_mux_clk, priv->default_mux_rate); + } + ++static u32 find_quot(struct device *dev, u32 freq, u32 baud, u32 *percent) ++{ ++ u32 quot; ++ u32 rate; ++ u64 hires_rate; ++ u64 hires_baud; ++ u64 hires_err; ++ ++ rate = freq / 16; ++ quot = DIV_ROUND_CLOSEST(rate, baud); ++ if (!quot) ++ return 0; ++ ++ /* increase resolution to get xx.xx percent */ ++ hires_rate = div_u64((u64)rate * 10000, (u64)quot); ++ hires_baud = (u64)baud * 10000; ++ ++ /* get the delta */ ++ if (hires_rate > hires_baud) ++ hires_err = (hires_rate - hires_baud); ++ else ++ hires_err = (hires_baud - hires_rate); ++ ++ *percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud); ++ ++ dev_dbg(dev, "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n", ++ baud, freq, *percent / 100, *percent % 100); ++ ++ return quot; ++} ++ + static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv, + u32 baud) + { + u32 percent; + u32 best_percent = UINT_MAX; + u32 quot; ++ u32 freq; + u32 best_quot = 1; +- u32 rate; +- int best_index = -1; +- u64 hires_rate; +- u64 hires_baud; +- u64 hires_err; ++ u32 best_freq = 0; + int rc; + int i; + int real_baud; +@@ -695,44 +723,35 @@ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv, + if (priv->baud_mux_clk == NULL) + return; + +- /* Find the closest match for specified baud */ +- for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) { +- if (priv->real_rates[i] == 0) +- continue; +- rate = priv->real_rates[i] / 16; +- quot = DIV_ROUND_CLOSEST(rate, baud); +- if (!quot) +- continue; +- +- /* increase resolution to get xx.xx percent */ +- hires_rate = (u64)rate * 10000; +- hires_baud = (u64)baud * 10000; +- +- hires_err = div_u64(hires_rate, (u64)quot); +- +- /* get the delta */ +- if (hires_err > hires_baud) +- hires_err = (hires_err - hires_baud); +- else +- hires_err = (hires_baud - hires_err); +- +- percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud); +- dev_dbg(up->dev, +- "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n", +- baud, priv->real_rates[i], percent / 100, +- percent % 100); +- if (percent < best_percent) { +- best_percent = percent; +- best_index = i; +- best_quot = quot; ++ /* Try default_mux_rate first */ ++ quot = find_quot(up->dev, priv->default_mux_rate, baud, &percent); ++ if (quot) { ++ best_percent = percent; ++ best_freq = priv->default_mux_rate; ++ best_quot = quot; ++ } ++ /* If more than 1% error, find the closest match for specified baud */ ++ if (best_percent > 100) { ++ for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) { ++ freq = priv->real_rates[i]; ++ if (freq == 0 || freq == priv->default_mux_rate) ++ continue; ++ quot = find_quot(up->dev, freq, baud, &percent); ++ if (!quot) ++ continue; ++ ++ if (percent < best_percent) { ++ best_percent = percent; ++ best_freq = freq; ++ best_quot = quot; ++ } + } + } +- if (best_index == -1) { ++ if (!best_freq) { + dev_err(up->dev, "Error, %d BAUD rate is too fast.\n", baud); + return; + } +- rate = priv->real_rates[best_index]; +- rc = clk_set_rate(priv->baud_mux_clk, rate); ++ rc = clk_set_rate(priv->baud_mux_clk, best_freq); + if (rc) + dev_err(up->dev, "Error selecting BAUD MUX clock\n"); + +@@ -741,8 +760,8 @@ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv, + dev_err(up->dev, "Error, baud: %d has %u.%u%% error\n", + baud, percent / 100, percent % 100); + +- real_baud = rate / 16 / best_quot; +- dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", rate); ++ real_baud = best_freq / 16 / best_quot; ++ dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", best_freq); + dev_dbg(up->dev, "Requested baud: %u, Actual baud: %u\n", + baud, real_baud); + +@@ -751,7 +770,7 @@ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv, + i += (i / 2); + priv->char_wait = ns_to_ktime(i); + +- up->uartclk = rate; ++ up->uartclk = best_freq; + } + + static void brcmstb_set_termios(struct uart_port *up, +diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c +index 9ff6bbe9c0863..d14988d1492fe 100644 +--- a/drivers/tty/serial/8250/8250_mtk.c ++++ b/drivers/tty/serial/8250/8250_mtk.c +@@ -209,15 +209,19 @@ static int mtk8250_startup(struct uart_port *port) + + static void mtk8250_shutdown(struct uart_port *port) + { +-#ifdef CONFIG_SERIAL_8250_DMA + struct uart_8250_port *up = up_to_u8250p(port); + struct mtk8250_data *data = port->private_data; ++ int irq = data->rx_wakeup_irq; + ++#ifdef CONFIG_SERIAL_8250_DMA + if (up->dma) + data->rx_status = DMA_RX_SHUTDOWN; + #endif + +- return serial8250_do_shutdown(port); ++ serial8250_do_shutdown(port); ++ ++ if (irq >= 0) ++ serial8250_do_set_mctrl(&up->port, TIOCM_RTS); + } + + static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask) +diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c +index 929206a9a6e11..12915fffac279 100644 +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -554,16 +554,28 @@ static bool sc16is7xx_regmap_noinc(struct device *dev, unsigned int reg) + return reg == SC16IS7XX_RHR_REG; + } + ++/* ++ * Configure programmable baud rate generator (divisor) according to the ++ * desired baud rate. ++ * ++ * From the datasheet, the divisor is computed according to: ++ * ++ * XTAL1 input frequency ++ * ----------------------- ++ * prescaler ++ * divisor = --------------------------- ++ * baud-rate x sampling-rate ++ */ + static int sc16is7xx_set_baud(struct uart_port *port, int baud) + { + struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); + u8 lcr; +- u8 prescaler = 0; ++ unsigned int prescaler = 1; + unsigned long clk = port->uartclk, div = clk / 16 / baud; + + if (div >= BIT(16)) { +- prescaler = SC16IS7XX_MCR_CLKSEL_BIT; +- div /= 4; ++ prescaler = 4; ++ div /= prescaler; + } + + /* Enable enhanced features */ +@@ -573,9 +585,10 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) + SC16IS7XX_EFR_ENABLE_BIT); + sc16is7xx_efr_unlock(port); + ++ /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */ + sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, + SC16IS7XX_MCR_CLKSEL_BIT, +- prescaler); ++ prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT); + + /* Backup LCR and access special register set (DLL/DLH) */ + lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); +@@ -591,7 +604,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) + /* Restore LCR and access to general register set */ + sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); + +- return DIV_ROUND_CLOSEST(clk / 16, div); ++ return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div); + } + + static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, +diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c +index 768bf87cd80d3..005d63ab1f441 100644 +--- a/drivers/ufs/core/ufs-mcq.c ++++ b/drivers/ufs/core/ufs-mcq.c +@@ -601,8 +601,7 @@ static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba, + addr = le64_to_cpu(cmd_desc_base_addr) & CQE_UCD_BA; + + while (sq_head_slot != hwq->sq_tail_slot) { +- utrd = hwq->sqe_base_addr + +- sq_head_slot * sizeof(struct utp_transfer_req_desc); ++ utrd = hwq->sqe_base_addr + sq_head_slot; + match = le64_to_cpu(utrd->command_desc_base_addr) & CQE_UCD_BA; + if (addr == match) { + ufshcd_mcq_nullify_sqe(utrd); +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index a0f8e930167d7..1322a9c318cff 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -4289,7 +4289,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) + * Make sure UIC command completion interrupt is disabled before + * issuing UIC command. + */ +- wmb(); ++ ufshcd_readl(hba, REG_INTERRUPT_ENABLE); + reenable_intr = true; + } + spin_unlock_irqrestore(hba->host->host_lock, flags); +@@ -10400,7 +10400,7 @@ int ufshcd_system_restore(struct device *dev) + * are updated with the latest queue addresses. Only after + * updating these addresses, we can queue the new commands. + */ +- mb(); ++ ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_BASE_H); + + /* Resuming from hibernate, assume that link was OFF */ + ufshcd_set_link_off(hba); +@@ -10621,7 +10621,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) + * Make sure that UFS interrupts are disabled and any pending interrupt + * status is cleared before registering UFS interrupt handler. + */ +- mb(); ++ ufshcd_readl(hba, REG_INTERRUPT_ENABLE); + + /* IRQ registration */ + err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba); +diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c +index bb30267da4711..66811d8d1929c 100644 +--- a/drivers/ufs/host/cdns-pltfrm.c ++++ b/drivers/ufs/host/cdns-pltfrm.c +@@ -136,7 +136,7 @@ static int cdns_ufs_set_hclkdiv(struct ufs_hba *hba) + * Make sure the register was updated, + * UniPro layer will not work with an incorrect value. + */ +- mb(); ++ ufshcd_readl(hba, CDNS_UFS_REG_HCLKDIV); + + return 0; + } +diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c +index 7a00004bfd036..62c343444d973 100644 +--- a/drivers/ufs/host/ufs-qcom.c ++++ b/drivers/ufs/host/ufs-qcom.c +@@ -284,9 +284,6 @@ static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host) + + if (host->hw_ver.major >= 0x05) + ufshcd_rmwl(host->hba, QUNIPRO_G4_SEL, 0, REG_UFS_CFG0); +- +- /* make sure above configuration is applied before we return */ +- mb(); + } + + /* +@@ -415,7 +412,7 @@ static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba) + REG_UFS_CFG2); + + /* Ensure that HW clock gating is enabled before next operations */ +- mb(); ++ ufshcd_readl(hba, REG_UFS_CFG2); + } + + static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, +@@ -507,7 +504,7 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, + * make sure above write gets applied before we return from + * this function. + */ +- mb(); ++ ufshcd_readl(hba, REG_UFS_SYS1CLK_1US); + } + + return 0; +diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h +index 9dd9a391ebb76..b9de170983c9e 100644 +--- a/drivers/ufs/host/ufs-qcom.h ++++ b/drivers/ufs/host/ufs-qcom.h +@@ -151,10 +151,10 @@ static inline void ufs_qcom_assert_reset(struct ufs_hba *hba) + ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, UFS_PHY_SOFT_RESET, REG_UFS_CFG1); + + /* +- * Make sure assertion of ufs phy reset is written to +- * register before returning ++ * Dummy read to ensure the write takes effect before doing any sort ++ * of delay + */ +- mb(); ++ ufshcd_readl(hba, REG_UFS_CFG1); + } + + static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba) +@@ -162,10 +162,10 @@ static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba) + ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, 0, REG_UFS_CFG1); + + /* +- * Make sure de-assertion of ufs phy reset is written to +- * register before returning ++ * Dummy read to ensure the write takes effect before doing any sort ++ * of delay + */ +- mb(); ++ ufshcd_readl(hba, REG_UFS_CFG1); + } + + /* Host controller hardware version: major.minor.step */ +diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig +index 197b6d5268e94..3f46663aa563d 100644 +--- a/drivers/video/fbdev/Kconfig ++++ b/drivers/video/fbdev/Kconfig +@@ -1648,8 +1648,8 @@ config FB_COBALT + select FB_IOMEM_HELPERS + + config FB_SH7760 +- bool "SH7760/SH7763/SH7720/SH7721 LCDC support" +- depends on FB=y && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ ++ tristate "SH7760/SH7763/SH7720/SH7721 LCDC support" ++ depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ + || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721) + select FB_IOMEM_HELPERS + help +diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig +index db09fe87fcd4f..0ab8848ba2f10 100644 +--- a/drivers/video/fbdev/core/Kconfig ++++ b/drivers/video/fbdev/core/Kconfig +@@ -144,6 +144,12 @@ config FB_DMAMEM_HELPERS + select FB_SYS_IMAGEBLIT + select FB_SYSMEM_FOPS + ++config FB_DMAMEM_HELPERS_DEFERRED ++ bool ++ depends on FB_CORE ++ select FB_DEFERRED_IO ++ select FB_DMAMEM_HELPERS ++ + config FB_IOMEM_FOPS + tristate + depends on FB_CORE +diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c +index eb2297b37504c..d35d2cf999988 100644 +--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c ++++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c +@@ -1575,7 +1575,7 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) + */ + info->fix = sh_mobile_lcdc_overlay_fix; + snprintf(info->fix.id, sizeof(info->fix.id), +- "SH Mobile LCDC Overlay %u", ovl->index); ++ "SHMobile ovl %u", ovl->index); + info->fix.smem_start = ovl->dma_handle; + info->fix.smem_len = ovl->fb_size; + info->fix.line_length = ovl->pitch; +diff --git a/drivers/video/fbdev/sis/init301.c b/drivers/video/fbdev/sis/init301.c +index a8fb41f1a2580..09329072004f4 100644 +--- a/drivers/video/fbdev/sis/init301.c ++++ b/drivers/video/fbdev/sis/init301.c +@@ -172,7 +172,7 @@ static const unsigned char SiS_HiTVGroup3_2[] = { + }; + + /* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */ +- ++#ifdef CONFIG_FB_SIS_315 + static const unsigned char SiS_Part2CLVX_1[] = { + 0x00,0x00, + 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, +@@ -245,7 +245,6 @@ static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */ + 0xFF,0xFF, + }; + +-#ifdef CONFIG_FB_SIS_315 + /* 661 et al LCD data structure (2.03.00) */ + static const unsigned char SiS_LCDStruct661[] = { + /* 1024x768 */ +diff --git a/drivers/virt/acrn/mm.c b/drivers/virt/acrn/mm.c +index fa5d9ca6be570..9c75de0656d8d 100644 +--- a/drivers/virt/acrn/mm.c ++++ b/drivers/virt/acrn/mm.c +@@ -155,43 +155,83 @@ int acrn_vm_memseg_unmap(struct acrn_vm *vm, struct acrn_vm_memmap *memmap) + int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap) + { + struct vm_memory_region_batch *regions_info; +- int nr_pages, i = 0, order, nr_regions = 0; ++ int nr_pages, i, order, nr_regions = 0; + struct vm_memory_mapping *region_mapping; + struct vm_memory_region_op *vm_region; + struct page **pages = NULL, *page; + void *remap_vaddr; + int ret, pinned; + u64 user_vm_pa; +- unsigned long pfn; + struct vm_area_struct *vma; + + if (!vm || !memmap) + return -EINVAL; + ++ /* Get the page number of the map region */ ++ nr_pages = memmap->len >> PAGE_SHIFT; ++ if (!nr_pages) ++ return -EINVAL; ++ + mmap_read_lock(current->mm); + vma = vma_lookup(current->mm, memmap->vma_base); + if (vma && ((vma->vm_flags & VM_PFNMAP) != 0)) { ++ unsigned long start_pfn, cur_pfn; ++ spinlock_t *ptl; ++ bool writable; ++ pte_t *ptep; ++ + if ((memmap->vma_base + memmap->len) > vma->vm_end) { + mmap_read_unlock(current->mm); + return -EINVAL; + } + +- ret = follow_pfn(vma, memmap->vma_base, &pfn); ++ for (i = 0; i < nr_pages; i++) { ++ ret = follow_pte(vma->vm_mm, ++ memmap->vma_base + i * PAGE_SIZE, ++ &ptep, &ptl); ++ if (ret) ++ break; ++ ++ cur_pfn = pte_pfn(ptep_get(ptep)); ++ if (i == 0) ++ start_pfn = cur_pfn; ++ writable = !!pte_write(ptep_get(ptep)); ++ pte_unmap_unlock(ptep, ptl); ++ ++ /* Disallow write access if the PTE is not writable. */ ++ if (!writable && ++ (memmap->attr & ACRN_MEM_ACCESS_WRITE)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ /* Disallow refcounted pages. */ ++ if (pfn_valid(cur_pfn) && ++ !PageReserved(pfn_to_page(cur_pfn))) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ /* Disallow non-contiguous ranges. */ ++ if (cur_pfn != start_pfn + i) { ++ ret = -EINVAL; ++ break; ++ } ++ } + mmap_read_unlock(current->mm); +- if (ret < 0) { ++ ++ if (ret) { + dev_dbg(acrn_dev.this_device, + "Failed to lookup PFN at VMA:%pK.\n", (void *)memmap->vma_base); + return ret; + } + + return acrn_mm_region_add(vm, memmap->user_vm_pa, +- PFN_PHYS(pfn), memmap->len, ++ PFN_PHYS(start_pfn), memmap->len, + ACRN_MEM_TYPE_WB, memmap->attr); + } + mmap_read_unlock(current->mm); + +- /* Get the page number of the map region */ +- nr_pages = memmap->len >> PAGE_SHIFT; + pages = vzalloc(array_size(nr_pages, sizeof(*pages))); + if (!pages) + return -ENOMEM; +@@ -235,12 +275,11 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap) + mutex_unlock(&vm->regions_mapping_lock); + + /* Calculate count of vm_memory_region_op */ +- while (i < nr_pages) { ++ for (i = 0; i < nr_pages; i += 1 << order) { + page = pages[i]; + VM_BUG_ON_PAGE(PageTail(page), page); + order = compound_order(page); + nr_regions++; +- i += 1 << order; + } + + /* Prepare the vm_memory_region_batch */ +@@ -257,8 +296,7 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap) + regions_info->vmid = vm->vmid; + regions_info->regions_gpa = virt_to_phys(vm_region); + user_vm_pa = memmap->user_vm_pa; +- i = 0; +- while (i < nr_pages) { ++ for (i = 0; i < nr_pages; i += 1 << order) { + u32 region_size; + + page = pages[i]; +@@ -274,7 +312,6 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap) + + vm_region++; + user_vm_pa += region_size; +- i += 1 << order; + } + + /* Inform the ACRN Hypervisor to set up EPT mappings */ +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 2776112dbdf8d..87f487b116577 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2773,13 +2773,19 @@ static int fiemap_next_leaf_item(struct btrfs_inode *inode, struct btrfs_path *p + goto out; + } + +- /* See the comment at fiemap_search_slot() about why we clone. */ +- copy_extent_buffer_full(clone, path->nodes[0]); + /* + * Important to preserve the start field, for the optimizations when + * checking if extents are shared (see extent_fiemap()). ++ * ++ * We must set ->start before calling copy_extent_buffer_full(). If we ++ * are on sub-pagesize blocksize, we use ->start to determine the offset ++ * into the folio where our eb exists, and if we update ->start after ++ * the fact then any subsequent reads of the eb may read from a ++ * different offset in the folio than where we originally copied into. + */ + clone->start = path->nodes[0]->start; ++ /* See the comment at fiemap_search_slot() about why we clone. */ ++ copy_extent_buffer_full(clone, path->nodes[0]); + + slot = path->slots[0]; + btrfs_release_path(path); +diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c +index 1f2f70a1b824e..decedc4ee15f6 100644 +--- a/fs/dlm/ast.c ++++ b/fs/dlm/ast.c +@@ -12,6 +12,7 @@ + #include <trace/events/dlm.h> + + #include "dlm_internal.h" ++#include "lvb_table.h" + #include "memory.h" + #include "lock.h" + #include "user.h" +@@ -42,6 +43,7 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode, + struct dlm_ls *ls = lkb->lkb_resource->res_ls; + int rv = DLM_ENQUEUE_CALLBACK_SUCCESS; + struct dlm_callback *cb; ++ int copy_lvb = 0; + int prev_mode; + + if (flags & DLM_CB_BAST) { +@@ -73,6 +75,17 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode, + goto out; + } + } ++ } else if (flags & DLM_CB_CAST) { ++ if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) { ++ if (lkb->lkb_last_cast) ++ prev_mode = lkb->lkb_last_cb->mode; ++ else ++ prev_mode = -1; ++ ++ if (!status && lkb->lkb_lksb->sb_lvbptr && ++ dlm_lvb_operations[prev_mode + 1][mode + 1]) ++ copy_lvb = 1; ++ } + } + + cb = dlm_allocate_cb(); +@@ -85,6 +98,7 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode, + cb->mode = mode; + cb->sb_status = status; + cb->sb_flags = (sbflags & 0x000000FF); ++ cb->copy_lvb = copy_lvb; + kref_init(&cb->ref); + if (!test_and_set_bit(DLM_IFL_CB_PENDING_BIT, &lkb->lkb_iflags)) + rv = DLM_ENQUEUE_CALLBACK_NEED_SCHED; +diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h +index 3b4dbce849f0f..a9137c90f3483 100644 +--- a/fs/dlm/dlm_internal.h ++++ b/fs/dlm/dlm_internal.h +@@ -222,6 +222,7 @@ struct dlm_callback { + int sb_status; /* copy to lksb status */ + uint8_t sb_flags; /* copy to lksb flags */ + int8_t mode; /* rq mode of bast, gr mode of cast */ ++ int copy_lvb; + + struct list_head list; + struct kref ref; +diff --git a/fs/dlm/user.c b/fs/dlm/user.c +index 9f9b68448830e..12a483deeef5e 100644 +--- a/fs/dlm/user.c ++++ b/fs/dlm/user.c +@@ -21,7 +21,6 @@ + #include "dlm_internal.h" + #include "lockspace.h" + #include "lock.h" +-#include "lvb_table.h" + #include "user.h" + #include "ast.h" + #include "config.h" +@@ -806,8 +805,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, + struct dlm_lkb *lkb; + DECLARE_WAITQUEUE(wait, current); + struct dlm_callback *cb; +- int rv, ret, copy_lvb = 0; +- int old_mode, new_mode; ++ int rv, ret; + + if (count == sizeof(struct dlm_device_version)) { + rv = copy_version_to_user(buf, count); +@@ -864,9 +862,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, + + lkb = list_first_entry(&proc->asts, struct dlm_lkb, lkb_cb_list); + +- /* rem_lkb_callback sets a new lkb_last_cast */ +- old_mode = lkb->lkb_last_cast->mode; +- + rv = dlm_dequeue_lkb_callback(lkb, &cb); + switch (rv) { + case DLM_DEQUEUE_CALLBACK_EMPTY: +@@ -895,12 +890,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, + if (cb->flags & DLM_CB_BAST) { + trace_dlm_bast(lkb->lkb_resource->res_ls, lkb, cb->mode); + } else if (cb->flags & DLM_CB_CAST) { +- new_mode = cb->mode; +- +- if (!cb->sb_status && lkb->lkb_lksb->sb_lvbptr && +- dlm_lvb_operations[old_mode + 1][new_mode + 1]) +- copy_lvb = 1; +- + lkb->lkb_lksb->sb_status = cb->sb_status; + lkb->lkb_lksb->sb_flags = cb->sb_flags; + trace_dlm_ast(lkb->lkb_resource->res_ls, lkb); +@@ -908,7 +897,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, + + ret = copy_result_to_user(lkb->lkb_ua, + test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), +- cb->flags, cb->mode, copy_lvb, buf, count); ++ cb->flags, cb->mode, cb->copy_lvb, buf, count); + + kref_put(&cb->ref, dlm_release_callback); + +diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c +index 3fe41964c0d8d..7f9f68c00ef63 100644 +--- a/fs/ecryptfs/keystore.c ++++ b/fs/ecryptfs/keystore.c +@@ -300,9 +300,11 @@ write_tag_66_packet(char *signature, u8 cipher_code, + * | Key Identifier Size | 1 or 2 bytes | + * | Key Identifier | arbitrary | + * | File Encryption Key Size | 1 or 2 bytes | ++ * | Cipher Code | 1 byte | + * | File Encryption Key | arbitrary | ++ * | Checksum | 2 bytes | + */ +- data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); ++ data_len = (8 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); + *packet = kmalloc(data_len, GFP_KERNEL); + message = *packet; + if (!message) { +diff --git a/fs/exec.c b/fs/exec.c +index cf1df7f16e55c..0c5f06d08c355 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -67,6 +67,7 @@ + #include <linux/time_namespace.h> + #include <linux/user_events.h> + #include <linux/rseq.h> ++#include <linux/ksm.h> + + #include <linux/uaccess.h> + #include <asm/mmu_context.h> +@@ -267,6 +268,14 @@ static int __bprm_mm_init(struct linux_binprm *bprm) + goto err_free; + } + ++ /* ++ * Need to be called with mmap write lock ++ * held, to avoid race with ksmd. ++ */ ++ err = ksm_execve(mm); ++ if (err) ++ goto err_ksm; ++ + /* + * Place the stack at the largest stack address the architecture + * supports. Later, we'll move this to an appropriate place. We don't +@@ -288,6 +297,8 @@ static int __bprm_mm_init(struct linux_binprm *bprm) + bprm->p = vma->vm_end - sizeof(void *); + return 0; + err: ++ ksm_exit(mm); ++err_ksm: + mmap_write_unlock(mm); + err_free: + bprm->vma = NULL; +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 537803250ca9a..6de6bf57699be 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2887,9 +2887,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, + if (IS_ERR(folio)) + return PTR_ERR(folio); + +- /* In case writeback began while the folio was unlocked */ +- folio_wait_stable(folio); +- + #ifdef CONFIG_FS_ENCRYPTION + ret = ext4_block_write_begin(folio, pos, len, ext4_da_get_block_prep); + #else +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 12b3f196010b8..714f83632e3f9 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -6113,6 +6113,7 @@ ext4_mb_new_blocks_simple(struct ext4_allocation_request *ar, int *errp) + ext4_mb_mark_bb(sb, block, 1, true); + ar->len = 1; + ++ *errp = 0; + return block; + } + +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 5e4f65c14dfb9..a630b27a4cc6e 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2897,7 +2897,7 @@ static int ext4_tmpfile(struct mnt_idmap *idmap, struct inode *dir, + inode = ext4_new_inode_start_handle(idmap, dir, mode, + NULL, 0, NULL, + EXT4_HT_DIR, +- EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) + ++ EXT4_MAXQUOTAS_TRANS_BLOCKS(dir->i_sb) + + 4 + EXT4_XATTR_TRANS_BLOCKS); + handle = ext4_journal_current_handle(); + err = PTR_ERR(inode); +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index eac698b8dd387..b01320502624a 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -179,22 +179,22 @@ static bool __f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, + break; + case META_SIT: + if (unlikely(blkaddr >= SIT_BLK_CNT(sbi))) +- goto err; ++ goto check_only; + break; + case META_SSA: + if (unlikely(blkaddr >= MAIN_BLKADDR(sbi) || + blkaddr < SM_I(sbi)->ssa_blkaddr)) +- goto err; ++ goto check_only; + break; + case META_CP: + if (unlikely(blkaddr >= SIT_I(sbi)->sit_base_addr || + blkaddr < __start_cp_addr(sbi))) +- goto err; ++ goto check_only; + break; + case META_POR: + if (unlikely(blkaddr >= MAX_BLKADDR(sbi) || + blkaddr < MAIN_BLKADDR(sbi))) +- goto err; ++ goto check_only; + break; + case DATA_GENERIC: + case DATA_GENERIC_ENHANCE: +@@ -228,6 +228,7 @@ static bool __f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, + return true; + err: + f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); ++check_only: + return false; + } + +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index 34540f9d011ca..2507fe34cbdf0 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -166,19 +166,45 @@ static bool glock_blocked_by_withdraw(struct gfs2_glock *gl) + return true; + } + +-void gfs2_glock_free(struct gfs2_glock *gl) ++static void __gfs2_glock_free(struct gfs2_glock *gl) + { +- struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; +- +- gfs2_glock_assert_withdraw(gl, atomic_read(&gl->gl_revokes) == 0); + rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms); + smp_mb(); + wake_up_glock(gl); + call_rcu(&gl->gl_rcu, gfs2_glock_dealloc); ++} ++ ++void gfs2_glock_free(struct gfs2_glock *gl) { ++ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; ++ ++ __gfs2_glock_free(gl); ++ if (atomic_dec_and_test(&sdp->sd_glock_disposal)) ++ wake_up(&sdp->sd_kill_wait); ++} ++ ++void gfs2_glock_free_later(struct gfs2_glock *gl) { ++ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; ++ ++ spin_lock(&lru_lock); ++ list_add(&gl->gl_lru, &sdp->sd_dead_glocks); ++ spin_unlock(&lru_lock); + if (atomic_dec_and_test(&sdp->sd_glock_disposal)) + wake_up(&sdp->sd_kill_wait); + } + ++static void gfs2_free_dead_glocks(struct gfs2_sbd *sdp) ++{ ++ struct list_head *list = &sdp->sd_dead_glocks; ++ ++ while(!list_empty(list)) { ++ struct gfs2_glock *gl; ++ ++ gl = list_first_entry(list, struct gfs2_glock, gl_lru); ++ list_del_init(&gl->gl_lru); ++ __gfs2_glock_free(gl); ++ } ++} ++ + /** + * gfs2_glock_hold() - increment reference count on glock + * @gl: The glock to hold +@@ -591,7 +617,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret) + struct gfs2_holder *gh; + unsigned state = ret & LM_OUT_ST_MASK; + +- spin_lock(&gl->gl_lockref.lock); + trace_gfs2_glock_state_change(gl, state); + state_change(gl, state); + gh = find_first_waiter(gl); +@@ -639,7 +664,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret) + gl->gl_target, state); + GLOCK_BUG_ON(gl, 1); + } +- spin_unlock(&gl->gl_lockref.lock); + return; + } + +@@ -662,7 +686,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret) + } + out: + clear_bit(GLF_LOCK, &gl->gl_flags); +- spin_unlock(&gl->gl_lockref.lock); + } + + static bool is_system_glock(struct gfs2_glock *gl) +@@ -690,6 +713,7 @@ __acquires(&gl->gl_lockref.lock) + { + const struct gfs2_glock_operations *glops = gl->gl_ops; + struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; ++ struct lm_lockstruct *ls = &sdp->sd_lockstruct; + unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0); + int ret; + +@@ -718,6 +742,9 @@ __acquires(&gl->gl_lockref.lock) + (gl->gl_state == LM_ST_EXCLUSIVE) || + (lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB))) + clear_bit(GLF_BLOCKING, &gl->gl_flags); ++ if (!glops->go_inval && !glops->go_sync) ++ goto skip_inval; ++ + spin_unlock(&gl->gl_lockref.lock); + if (glops->go_sync) { + ret = glops->go_sync(gl); +@@ -730,6 +757,7 @@ __acquires(&gl->gl_lockref.lock) + fs_err(sdp, "Error %d syncing glock \n", ret); + gfs2_dump_glock(NULL, gl, true); + } ++ spin_lock(&gl->gl_lockref.lock); + goto skip_inval; + } + } +@@ -750,9 +778,10 @@ __acquires(&gl->gl_lockref.lock) + glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA); + clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); + } ++ spin_lock(&gl->gl_lockref.lock); + + skip_inval: +- gfs2_glock_hold(gl); ++ gl->gl_lockref.count++; + /* + * Check for an error encountered since we called go_sync and go_inval. + * If so, we can't withdraw from the glock code because the withdraw +@@ -794,31 +823,37 @@ __acquires(&gl->gl_lockref.lock) + */ + clear_bit(GLF_LOCK, &gl->gl_flags); + clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags); +- gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD); +- goto out; ++ __gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD); ++ return; + } else { + clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); + } + } + +- if (sdp->sd_lockstruct.ls_ops->lm_lock) { +- /* lock_dlm */ +- ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags); ++ if (ls->ls_ops->lm_lock) { ++ spin_unlock(&gl->gl_lockref.lock); ++ ret = ls->ls_ops->lm_lock(gl, target, lck_flags); ++ spin_lock(&gl->gl_lockref.lock); ++ + if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED && + target == LM_ST_UNLOCKED && +- test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags)) { +- finish_xmote(gl, target); +- gfs2_glock_queue_work(gl, 0); ++ test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) { ++ /* ++ * The lockspace has been released and the lock has ++ * been unlocked implicitly. ++ */ + } else if (ret) { + fs_err(sdp, "lm_lock ret %d\n", ret); +- GLOCK_BUG_ON(gl, !gfs2_withdrawing_or_withdrawn(sdp)); ++ target = gl->gl_state | LM_OUT_ERROR; ++ } else { ++ /* The operation will be completed asynchronously. */ ++ return; + } +- } else { /* lock_nolock */ +- finish_xmote(gl, target); +- gfs2_glock_queue_work(gl, 0); + } +-out: +- spin_lock(&gl->gl_lockref.lock); ++ ++ /* Complete the operation now. */ ++ finish_xmote(gl, target); ++ __gfs2_glock_queue_work(gl, 0); + } + + /** +@@ -1071,11 +1106,12 @@ static void glock_work_func(struct work_struct *work) + struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); + unsigned int drop_refs = 1; + +- if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) { ++ spin_lock(&gl->gl_lockref.lock); ++ if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) { ++ clear_bit(GLF_REPLY_PENDING, &gl->gl_flags); + finish_xmote(gl, gl->gl_reply); + drop_refs++; + } +- spin_lock(&gl->gl_lockref.lock); + if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && + gl->gl_state != LM_ST_UNLOCKED && + gl->gl_demote_state != LM_ST_EXCLUSIVE) { +@@ -2148,8 +2184,11 @@ static void thaw_glock(struct gfs2_glock *gl) + return; + if (!lockref_get_not_dead(&gl->gl_lockref)) + return; ++ ++ spin_lock(&gl->gl_lockref.lock); + set_bit(GLF_REPLY_PENDING, &gl->gl_flags); +- gfs2_glock_queue_work(gl, 0); ++ __gfs2_glock_queue_work(gl, 0); ++ spin_unlock(&gl->gl_lockref.lock); + } + + /** +@@ -2225,6 +2264,8 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) + wait_event_timeout(sdp->sd_kill_wait, + atomic_read(&sdp->sd_glock_disposal) == 0, + HZ * 600); ++ gfs2_lm_unmount(sdp); ++ gfs2_free_dead_glocks(sdp); + glock_hash_walk(dump_glock_func, sdp); + } + +diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h +index 0114f3e0ebe01..86987a59a0580 100644 +--- a/fs/gfs2/glock.h ++++ b/fs/gfs2/glock.h +@@ -252,6 +252,7 @@ void gfs2_gl_dq_holders(struct gfs2_sbd *sdp); + void gfs2_glock_thaw(struct gfs2_sbd *sdp); + void gfs2_glock_add_to_lru(struct gfs2_glock *gl); + void gfs2_glock_free(struct gfs2_glock *gl); ++void gfs2_glock_free_later(struct gfs2_glock *gl); + + int __init gfs2_glock_init(void); + void gfs2_glock_exit(void); +diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c +index 45653cbc8a87d..e0e8dfeee777d 100644 +--- a/fs/gfs2/glops.c ++++ b/fs/gfs2/glops.c +@@ -82,6 +82,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync, + GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count)); + spin_unlock(&sdp->sd_ail_lock); + gfs2_log_unlock(sdp); ++ ++ if (gfs2_withdrawing(sdp)) ++ gfs2_withdraw(sdp); + } + + +diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h +index 95a334d64da2a..60abd7050c998 100644 +--- a/fs/gfs2/incore.h ++++ b/fs/gfs2/incore.h +@@ -838,6 +838,7 @@ struct gfs2_sbd { + /* For quiescing the filesystem */ + struct gfs2_holder sd_freeze_gh; + struct mutex sd_freeze_mutex; ++ struct list_head sd_dead_glocks; + + char sd_fsname[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2]; + char sd_table_name[GFS2_FSNAME_LEN]; +diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c +index d1ac5d0679ea6..e028e55e67d95 100644 +--- a/fs/gfs2/lock_dlm.c ++++ b/fs/gfs2/lock_dlm.c +@@ -121,6 +121,11 @@ static void gdlm_ast(void *arg) + struct gfs2_glock *gl = arg; + unsigned ret = gl->gl_state; + ++ /* If the glock is dead, we only react to a dlm_unlock() reply. */ ++ if (__lockref_is_dead(&gl->gl_lockref) && ++ gl->gl_lksb.sb_status != -DLM_EUNLOCK) ++ return; ++ + gfs2_update_reply_times(gl); + BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); + +@@ -171,6 +176,9 @@ static void gdlm_bast(void *arg, int mode) + { + struct gfs2_glock *gl = arg; + ++ if (__lockref_is_dead(&gl->gl_lockref)) ++ return; ++ + switch (mode) { + case DLM_LOCK_EX: + gfs2_glock_cb(gl, LM_ST_UNLOCKED); +@@ -291,8 +299,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl) + struct lm_lockstruct *ls = &sdp->sd_lockstruct; + int error; + +- if (gl->gl_lksb.sb_lkid == 0) +- goto out_free; ++ BUG_ON(!__lockref_is_dead(&gl->gl_lockref)); ++ ++ if (gl->gl_lksb.sb_lkid == 0) { ++ gfs2_glock_free(gl); ++ return; ++ } + + clear_bit(GLF_BLOCKING, &gl->gl_flags); + gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); +@@ -300,13 +312,17 @@ static void gdlm_put_lock(struct gfs2_glock *gl) + gfs2_update_request_times(gl); + + /* don't want to call dlm if we've unmounted the lock protocol */ +- if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) +- goto out_free; ++ if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) { ++ gfs2_glock_free(gl); ++ return; ++ } + /* don't want to skip dlm_unlock writing the lvb when lock has one */ + + if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) && +- !gl->gl_lksb.sb_lvbptr) +- goto out_free; ++ !gl->gl_lksb.sb_lvbptr) { ++ gfs2_glock_free_later(gl); ++ return; ++ } + + again: + error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, +@@ -321,10 +337,6 @@ static void gdlm_put_lock(struct gfs2_glock *gl) + gl->gl_name.ln_type, + (unsigned long long)gl->gl_name.ln_number, error); + } +- return; +- +-out_free: +- gfs2_glock_free(gl); + } + + static void gdlm_cancel(struct gfs2_glock *gl) +diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c +index 572d58e86296f..cde7118599abb 100644 +--- a/fs/gfs2/ops_fstype.c ++++ b/fs/gfs2/ops_fstype.c +@@ -136,6 +136,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) + atomic_set(&sdp->sd_log_in_flight, 0); + init_waitqueue_head(&sdp->sd_log_flush_wait); + mutex_init(&sdp->sd_freeze_mutex); ++ INIT_LIST_HEAD(&sdp->sd_dead_glocks); + + return sdp; + +diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c +index e5f79466340d2..2d780b4701a23 100644 +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -646,10 +646,7 @@ static void gfs2_put_super(struct super_block *sb) + gfs2_gl_hash_clear(sdp); + truncate_inode_pages_final(&sdp->sd_aspace); + gfs2_delete_debugfs_file(sdp); +- /* Unmount the locking protocol */ +- gfs2_lm_unmount(sdp); + +- /* At this point, we're through participating in the lockspace */ + gfs2_sys_fs_del(sdp); + free_sbd(sdp); + } +diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c +index f52141ce94853..fc3ecb180ac53 100644 +--- a/fs/gfs2/util.c ++++ b/fs/gfs2/util.c +@@ -350,7 +350,6 @@ int gfs2_withdraw(struct gfs2_sbd *sdp) + fs_err(sdp, "telling LM to unmount\n"); + lm->lm_unmount(sdp); + } +- set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags); + fs_err(sdp, "File system withdrawn\n"); + dump_stack(); + clear_bit(SDF_WITHDRAW_IN_PROG, &sdp->sd_flags); +diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c +index 00224f3a8d6e7..defb4162c3d5b 100644 +--- a/fs/jffs2/xattr.c ++++ b/fs/jffs2/xattr.c +@@ -1110,6 +1110,9 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, + return rc; + + request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size); ++ if (request > c->sector_size - c->cleanmarker_size) ++ return -ERANGE; ++ + rc = jffs2_reserve_space(c, request, &length, + ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE); + if (rc) { +diff --git a/fs/libfs.c b/fs/libfs.c +index 3a6f2cb364f8c..b635ee5adbcce 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -295,6 +295,18 @@ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry) + return 0; + } + ++static int simple_offset_replace(struct offset_ctx *octx, struct dentry *dentry, ++ long offset) ++{ ++ int ret; ++ ++ ret = mtree_store(&octx->mt, offset, dentry, GFP_KERNEL); ++ if (ret) ++ return ret; ++ offset_set(dentry, offset); ++ return 0; ++} ++ + /** + * simple_offset_remove - Remove an entry to a directory's offset map + * @octx: directory offset ctx to be updated +@@ -345,6 +357,36 @@ int simple_offset_empty(struct dentry *dentry) + return ret; + } + ++/** ++ * simple_offset_rename - handle directory offsets for rename ++ * @old_dir: parent directory of source entry ++ * @old_dentry: dentry of source entry ++ * @new_dir: parent_directory of destination entry ++ * @new_dentry: dentry of destination ++ * ++ * Caller provides appropriate serialization. ++ * ++ * User space expects the directory offset value of the replaced ++ * (new) directory entry to be unchanged after a rename. ++ * ++ * Returns zero on success, a negative errno value on failure. ++ */ ++int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry) ++{ ++ struct offset_ctx *old_ctx = old_dir->i_op->get_offset_ctx(old_dir); ++ struct offset_ctx *new_ctx = new_dir->i_op->get_offset_ctx(new_dir); ++ long new_offset = dentry2offset(new_dentry); ++ ++ simple_offset_remove(old_ctx, old_dentry); ++ ++ if (new_offset) { ++ offset_set(new_dentry, 0); ++ return simple_offset_replace(new_ctx, old_dentry, new_offset); ++ } ++ return simple_offset_add(new_ctx, old_dentry); ++} ++ + /** + * simple_offset_rename_exchange - exchange rename with directory offsets + * @old_dir: parent of dentry being moved +@@ -352,6 +394,9 @@ int simple_offset_empty(struct dentry *dentry) + * @new_dir: destination parent + * @new_dentry: destination dentry + * ++ * This API preserves the directory offset values. Caller provides ++ * appropriate serialization. ++ * + * Returns zero on success. Otherwise a negative errno is returned and the + * rename is rolled back. + */ +@@ -369,11 +414,11 @@ int simple_offset_rename_exchange(struct inode *old_dir, + simple_offset_remove(old_ctx, old_dentry); + simple_offset_remove(new_ctx, new_dentry); + +- ret = simple_offset_add(new_ctx, old_dentry); ++ ret = simple_offset_replace(new_ctx, old_dentry, new_index); + if (ret) + goto out_restore; + +- ret = simple_offset_add(old_ctx, new_dentry); ++ ret = simple_offset_replace(old_ctx, new_dentry, old_index); + if (ret) { + simple_offset_remove(new_ctx, old_dentry); + goto out_restore; +@@ -388,10 +433,8 @@ int simple_offset_rename_exchange(struct inode *old_dir, + return 0; + + out_restore: +- offset_set(old_dentry, old_index); +- mtree_store(&old_ctx->mt, old_index, old_dentry, GFP_KERNEL); +- offset_set(new_dentry, new_index); +- mtree_store(&new_ctx->mt, new_index, new_dentry, GFP_KERNEL); ++ (void)simple_offset_replace(old_ctx, old_dentry, old_index); ++ (void)simple_offset_replace(new_ctx, new_dentry, new_index); + return ret; + } + +diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c +index ecd18bffeebc7..4d23bb1d08c0a 100644 +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -48,12 +48,10 @@ enum { + NFSD_MaxBlkSize, + NFSD_MaxConnections, + NFSD_Filecache, +-#ifdef CONFIG_NFSD_V4 + NFSD_Leasetime, + NFSD_Gracetime, + NFSD_RecoveryDir, + NFSD_V4EndGrace, +-#endif + NFSD_MaxReserved + }; + +@@ -1360,7 +1358,9 @@ static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc) + #ifdef CONFIG_NFSD_V4 + [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, + [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, ++#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING + [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, ++#endif + [NFSD_V4EndGrace] = {"v4_end_grace", &transaction_ops, S_IWUSR|S_IRUGO}, + #endif + /* last one */ {""} +diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c +index f1a01c191cf53..8be471ce4f195 100644 +--- a/fs/nilfs2/ioctl.c ++++ b/fs/nilfs2/ioctl.c +@@ -60,7 +60,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, + if (argv->v_nmembs == 0) + return 0; + +- if (argv->v_size > PAGE_SIZE) ++ if ((size_t)argv->v_size > PAGE_SIZE) + return -EINVAL; + + /* +diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c +index aa5290cb7467c..3c1e4e9eafa31 100644 +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -2124,8 +2124,10 @@ static void nilfs_segctor_start_timer(struct nilfs_sc_info *sci) + { + spin_lock(&sci->sc_state_lock); + if (!(sci->sc_state & NILFS_SEGCTOR_COMMIT)) { +- sci->sc_timer.expires = jiffies + sci->sc_interval; +- add_timer(&sci->sc_timer); ++ if (sci->sc_task) { ++ sci->sc_timer.expires = jiffies + sci->sc_interval; ++ add_timer(&sci->sc_timer); ++ } + sci->sc_state |= NILFS_SEGCTOR_COMMIT; + } + spin_unlock(&sci->sc_state_lock); +@@ -2172,19 +2174,36 @@ static int nilfs_segctor_sync(struct nilfs_sc_info *sci) + struct nilfs_segctor_wait_request wait_req; + int err = 0; + +- spin_lock(&sci->sc_state_lock); + init_wait(&wait_req.wq); + wait_req.err = 0; + atomic_set(&wait_req.done, 0); ++ init_waitqueue_entry(&wait_req.wq, current); ++ ++ /* ++ * To prevent a race issue where completion notifications from the ++ * log writer thread are missed, increment the request sequence count ++ * "sc_seq_request" and insert a wait queue entry using the current ++ * sequence number into the "sc_wait_request" queue at the same time ++ * within the lock section of "sc_state_lock". ++ */ ++ spin_lock(&sci->sc_state_lock); + wait_req.seq = ++sci->sc_seq_request; ++ add_wait_queue(&sci->sc_wait_request, &wait_req.wq); + spin_unlock(&sci->sc_state_lock); + +- init_waitqueue_entry(&wait_req.wq, current); +- add_wait_queue(&sci->sc_wait_request, &wait_req.wq); +- set_current_state(TASK_INTERRUPTIBLE); + wake_up(&sci->sc_wait_daemon); + + for (;;) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ /* ++ * Synchronize only while the log writer thread is alive. ++ * Leave flushing out after the log writer thread exits to ++ * the cleanup work in nilfs_segctor_destroy(). ++ */ ++ if (!sci->sc_task) ++ break; ++ + if (atomic_read(&wait_req.done)) { + err = wait_req.err; + break; +@@ -2200,7 +2219,7 @@ static int nilfs_segctor_sync(struct nilfs_sc_info *sci) + return err; + } + +-static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) ++static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err, bool force) + { + struct nilfs_segctor_wait_request *wrq, *n; + unsigned long flags; +@@ -2208,7 +2227,7 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) + spin_lock_irqsave(&sci->sc_wait_request.lock, flags); + list_for_each_entry_safe(wrq, n, &sci->sc_wait_request.head, wq.entry) { + if (!atomic_read(&wrq->done) && +- nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq)) { ++ (force || nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq))) { + wrq->err = err; + atomic_set(&wrq->done, 1); + } +@@ -2326,10 +2345,21 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, + */ + static void nilfs_segctor_accept(struct nilfs_sc_info *sci) + { ++ bool thread_is_alive; ++ + spin_lock(&sci->sc_state_lock); + sci->sc_seq_accepted = sci->sc_seq_request; ++ thread_is_alive = (bool)sci->sc_task; + spin_unlock(&sci->sc_state_lock); +- del_timer_sync(&sci->sc_timer); ++ ++ /* ++ * This function does not race with the log writer thread's ++ * termination. Therefore, deleting sc_timer, which should not be ++ * done after the log writer thread exits, can be done safely outside ++ * the area protected by sc_state_lock. ++ */ ++ if (thread_is_alive) ++ del_timer_sync(&sci->sc_timer); + } + + /** +@@ -2346,7 +2376,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) + if (mode == SC_LSEG_SR) { + sci->sc_state &= ~NILFS_SEGCTOR_COMMIT; + sci->sc_seq_done = sci->sc_seq_accepted; +- nilfs_segctor_wakeup(sci, err); ++ nilfs_segctor_wakeup(sci, err, false); + sci->sc_flush_request = 0; + } else { + if (mode == SC_FLUSH_FILE) +@@ -2355,7 +2385,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) + sci->sc_flush_request &= ~FLUSH_DAT_BIT; + + /* re-enable timer if checkpoint creation was not done */ +- if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && ++ if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && sci->sc_task && + time_before(jiffies, sci->sc_timer.expires)) + add_timer(&sci->sc_timer); + } +@@ -2545,6 +2575,7 @@ static int nilfs_segctor_thread(void *arg) + int timeout = 0; + + sci->sc_timer_task = current; ++ timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0); + + /* start sync. */ + sci->sc_task = current; +@@ -2612,6 +2643,7 @@ static int nilfs_segctor_thread(void *arg) + end_thread: + /* end sync. */ + sci->sc_task = NULL; ++ timer_shutdown_sync(&sci->sc_timer); + wake_up(&sci->sc_wait_task); /* for nilfs_segctor_kill_thread() */ + spin_unlock(&sci->sc_state_lock); + return 0; +@@ -2675,7 +2707,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, + INIT_LIST_HEAD(&sci->sc_gc_inodes); + INIT_LIST_HEAD(&sci->sc_iput_queue); + INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func); +- timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0); + + sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; + sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; +@@ -2729,6 +2760,13 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) + || sci->sc_seq_request != sci->sc_seq_done); + spin_unlock(&sci->sc_state_lock); + ++ /* ++ * Forcibly wake up tasks waiting in nilfs_segctor_sync(), which can ++ * be called from delayed iput() via nilfs_evict_inode() and can race ++ * with the above log writer thread termination. ++ */ ++ nilfs_segctor_wakeup(sci, 0, true); ++ + if (flush_work(&sci->sc_iput_work)) + flag = true; + +@@ -2754,7 +2792,6 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) + + down_write(&nilfs->ns_segctor_sem); + +- timer_shutdown_sync(&sci->sc_timer); + kfree(sci); + } + +diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c +index 263635199b60d..1937e8e612f87 100644 +--- a/fs/ntfs3/dir.c ++++ b/fs/ntfs3/dir.c +@@ -475,6 +475,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx) + vbo = (u64)bit << index_bits; + if (vbo >= i_size) { + ntfs_inode_err(dir, "Looks like your dir is corrupt"); ++ ctx->pos = eod; + err = -EINVAL; + goto out; + } +diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c +index daabaad63aaf6..14284f0ed46aa 100644 +--- a/fs/ntfs3/index.c ++++ b/fs/ntfs3/index.c +@@ -1533,6 +1533,11 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, + goto out1; + } + ++ if (data_size <= le64_to_cpu(alloc->nres.data_size)) { ++ /* Reuse index. */ ++ goto out; ++ } ++ + /* Increase allocation. */ + err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len, + &indx->alloc_run, data_size, &data_size, true, +@@ -1546,6 +1551,7 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, + if (in->name == I30_NAME) + i_size_write(&ni->vfs_inode, data_size); + ++out: + *vbn = bit << indx->idx2vbn_bits; + + return 0; +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index d273eda1cf45d..ba5a39a2f957d 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -37,7 +37,7 @@ static struct inode *ntfs_read_mft(struct inode *inode, + bool is_dir; + unsigned long ino = inode->i_ino; + u32 rp_fa = 0, asize, t32; +- u16 roff, rsize, names = 0; ++ u16 roff, rsize, names = 0, links = 0; + const struct ATTR_FILE_NAME *fname = NULL; + const struct INDEX_ROOT *root; + struct REPARSE_DATA_BUFFER rp; // 0x18 bytes +@@ -200,11 +200,12 @@ static struct inode *ntfs_read_mft(struct inode *inode, + rsize < SIZEOF_ATTRIBUTE_FILENAME) + goto out; + ++ names += 1; + fname = Add2Ptr(attr, roff); + if (fname->type == FILE_NAME_DOS) + goto next_attr; + +- names += 1; ++ links += 1; + if (name && name->len == fname->name_len && + !ntfs_cmp_names_cpu(name, (struct le_str *)&fname->name_len, + NULL, false)) +@@ -429,7 +430,7 @@ static struct inode *ntfs_read_mft(struct inode *inode, + ni->mi.dirty = true; + } + +- set_nlink(inode, names); ++ set_nlink(inode, links); + + if (S_ISDIR(mode)) { + ni->std_fa |= FILE_ATTRIBUTE_DIRECTORY; +diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c +index 6aa3a9d44df1b..6c76503edc200 100644 +--- a/fs/ntfs3/record.c ++++ b/fs/ntfs3/record.c +@@ -534,16 +534,9 @@ bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi, + if (aoff + asize > used) + return false; + +- if (ni && is_attr_indexed(attr)) { ++ if (ni && is_attr_indexed(attr) && attr->type == ATTR_NAME) { + u16 links = le16_to_cpu(ni->mi.mrec->hard_links); +- struct ATTR_FILE_NAME *fname = +- attr->type != ATTR_NAME ? +- NULL : +- resident_data_ex(attr, +- SIZEOF_ATTRIBUTE_FILENAME); +- if (fname && fname->type == FILE_NAME_DOS) { +- /* Do not decrease links count deleting DOS name. */ +- } else if (!links) { ++ if (!links) { + /* minor error. Not critical. */ + } else { + ni->mi.mrec->hard_links = cpu_to_le16(links - 1); +diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c +index b26d95a8d3274..0ed534f759e92 100644 +--- a/fs/ntfs3/super.c ++++ b/fs/ntfs3/super.c +@@ -1861,8 +1861,6 @@ static int __init init_ntfs_fs(void) + { + int err; + +- pr_info("ntfs3: Max link count %u\n", NTFS_LINK_MAX); +- + if (IS_ENABLED(CONFIG_NTFS3_FS_POSIX_ACL)) + pr_info("ntfs3: Enabled Linux POSIX ACLs support\n"); + if (IS_ENABLED(CONFIG_NTFS3_64BIT_CLUSTER)) +diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c +index 4a0779e3ef792..a7b527ea50d3c 100644 +--- a/fs/openpromfs/inode.c ++++ b/fs/openpromfs/inode.c +@@ -355,10 +355,10 @@ static struct inode *openprom_iget(struct super_block *sb, ino_t ino) + return inode; + } + +-static int openprom_remount(struct super_block *sb, int *flags, char *data) ++static int openpromfs_reconfigure(struct fs_context *fc) + { +- sync_filesystem(sb); +- *flags |= SB_NOATIME; ++ sync_filesystem(fc->root->d_sb); ++ fc->sb_flags |= SB_NOATIME; + return 0; + } + +@@ -366,7 +366,6 @@ static const struct super_operations openprom_sops = { + .alloc_inode = openprom_alloc_inode, + .free_inode = openprom_free_inode, + .statfs = simple_statfs, +- .remount_fs = openprom_remount, + }; + + static int openprom_fill_super(struct super_block *s, struct fs_context *fc) +@@ -415,6 +414,7 @@ static int openpromfs_get_tree(struct fs_context *fc) + + static const struct fs_context_operations openpromfs_context_ops = { + .get_tree = openpromfs_get_tree, ++ .reconfigure = openpromfs_reconfigure, + }; + + static int openpromfs_init_fs_context(struct fs_context *fc) +diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c +index a2f0a2edceb8a..e0a6b758094fc 100644 +--- a/fs/smb/server/mgmt/share_config.c ++++ b/fs/smb/server/mgmt/share_config.c +@@ -165,8 +165,12 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um, + + share->path = kstrndup(ksmbd_share_config_path(resp), path_len, + GFP_KERNEL); +- if (share->path) ++ if (share->path) { + share->path_sz = strlen(share->path); ++ while (share->path_sz > 1 && ++ share->path[share->path_sz - 1] == '/') ++ share->path[--share->path_sz] = '\0'; ++ } + share->create_mask = resp->create_mask; + share->directory_mask = resp->directory_mask; + share->force_create_mode = resp->force_create_mode; +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index b9d9116fc2b3f..a8f52c4ebbdad 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -610,19 +610,24 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level) + if (opinfo->op_state == OPLOCK_CLOSING) + return -ENOENT; + else if (opinfo->level <= req_op_level) { +- if (opinfo->is_lease && +- opinfo->o_lease->state != +- (SMB2_LEASE_HANDLE_CACHING_LE | +- SMB2_LEASE_READ_CACHING_LE)) ++ if (opinfo->is_lease == false) ++ return 1; ++ ++ if (opinfo->o_lease->state != ++ (SMB2_LEASE_HANDLE_CACHING_LE | ++ SMB2_LEASE_READ_CACHING_LE)) + return 1; + } + } + + if (opinfo->level <= req_op_level) { +- if (opinfo->is_lease && +- opinfo->o_lease->state != +- (SMB2_LEASE_HANDLE_CACHING_LE | +- SMB2_LEASE_READ_CACHING_LE)) { ++ if (opinfo->is_lease == false) { ++ wake_up_oplock_break(opinfo); ++ return 1; ++ } ++ if (opinfo->o_lease->state != ++ (SMB2_LEASE_HANDLE_CACHING_LE | ++ SMB2_LEASE_READ_CACHING_LE)) { + wake_up_oplock_break(opinfo); + return 1; + } +diff --git a/include/drm/drm_displayid.h b/include/drm/drm_displayid.h +index 566497eeb3b81..bc1f6b378195f 100644 +--- a/include/drm/drm_displayid.h ++++ b/include/drm/drm_displayid.h +@@ -30,7 +30,6 @@ struct drm_edid; + #define VESA_IEEE_OUI 0x3a0292 + + /* DisplayID Structure versions */ +-#define DISPLAY_ID_STRUCTURE_VER_12 0x12 + #define DISPLAY_ID_STRUCTURE_VER_20 0x20 + + /* DisplayID Structure v1r2 Data Blocks */ +diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h +index c0aec0d4d664e..3011d33eccbd2 100644 +--- a/include/drm/drm_mipi_dsi.h ++++ b/include/drm/drm_mipi_dsi.h +@@ -241,9 +241,9 @@ int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi); + int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi); + int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi, + u16 value); +-ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable); +-ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, +- const struct drm_dsc_picture_parameter_set *pps); ++int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable); ++int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, ++ const struct drm_dsc_picture_parameter_set *pps); + + ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload, + size_t size); +diff --git a/include/linux/acpi.h b/include/linux/acpi.h +index 34829f2c517ac..168201e4c7827 100644 +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -573,9 +573,13 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); + #define OSC_SB_CPCV2_SUPPORT 0x00000040 + #define OSC_SB_PCLPI_SUPPORT 0x00000080 + #define OSC_SB_OSLPI_SUPPORT 0x00000100 ++#define OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT 0x00000200 ++#define OSC_SB_OVER_16_PSTATES_SUPPORT 0x00000400 ++#define OSC_SB_GED_SUPPORT 0x00000800 + #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 +-#define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 ++#define OSC_SB_IRQ_RESOURCE_SOURCE_SUPPORT 0x00002000 + #define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000 ++#define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00020000 + #define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000 + #define OSC_SB_PRM_SUPPORT 0x00200000 + #define OSC_SB_FFH_OPR_SUPPORT 0x00400000 +diff --git a/include/linux/bitops.h b/include/linux/bitops.h +index 2ba557e067fe6..f7f5a783da2aa 100644 +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -80,6 +80,7 @@ __check_bitop_pr(__test_and_set_bit); + __check_bitop_pr(__test_and_clear_bit); + __check_bitop_pr(__test_and_change_bit); + __check_bitop_pr(test_bit); ++__check_bitop_pr(test_bit_acquire); + + #undef __check_bitop_pr + +diff --git a/include/linux/dev_printk.h b/include/linux/dev_printk.h +index 6bfe70decc9fb..ae80a303c216b 100644 +--- a/include/linux/dev_printk.h ++++ b/include/linux/dev_printk.h +@@ -129,6 +129,16 @@ void _dev_info(const struct device *dev, const char *fmt, ...) + _dev_printk(level, dev, fmt, ##__VA_ARGS__); \ + }) + ++/* ++ * Dummy dev_printk for disabled debugging statements to use whilst maintaining ++ * gcc's format checking. ++ */ ++#define dev_no_printk(level, dev, fmt, ...) \ ++ ({ \ ++ if (0) \ ++ _dev_printk(level, dev, fmt, ##__VA_ARGS__); \ ++ }) ++ + /* + * #defines for all the dev_<level> macros to prefix with whatever + * possible use of #define dev_fmt(fmt) ... +@@ -158,10 +168,7 @@ void _dev_info(const struct device *dev, const char *fmt, ...) + dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__) + #else + #define dev_dbg(dev, fmt, ...) \ +-({ \ +- if (0) \ +- dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \ +-}) ++ dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__) + #endif + + #ifdef CONFIG_PRINTK +@@ -247,20 +254,14 @@ do { \ + } while (0) + #else + #define dev_dbg_ratelimited(dev, fmt, ...) \ +-do { \ +- if (0) \ +- dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \ +-} while (0) ++ dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__) + #endif + + #ifdef VERBOSE_DEBUG + #define dev_vdbg dev_dbg + #else + #define dev_vdbg(dev, fmt, ...) \ +-({ \ +- if (0) \ +- dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \ +-}) ++ dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__) + #endif + + /* +diff --git a/include/linux/fb.h b/include/linux/fb.h +index 0dd27364d56fe..811e47f9d1c3f 100644 +--- a/include/linux/fb.h ++++ b/include/linux/fb.h +@@ -694,6 +694,10 @@ extern int fb_deferred_io_fsync(struct file *file, loff_t start, + __FB_GEN_DEFAULT_DEFERRED_OPS_RDWR(__prefix, __damage_range, sys) \ + __FB_GEN_DEFAULT_DEFERRED_OPS_DRAW(__prefix, __damage_area, sys) + ++#define FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(__prefix, __damage_range, __damage_area) \ ++ __FB_GEN_DEFAULT_DEFERRED_OPS_RDWR(__prefix, __damage_range, sys) \ ++ __FB_GEN_DEFAULT_DEFERRED_OPS_DRAW(__prefix, __damage_area, sys) ++ + /* + * Initializes struct fb_ops for deferred I/O. + */ +diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h +index 6aeebe0a67770..6eaa190d0083c 100644 +--- a/include/linux/fortify-string.h ++++ b/include/linux/fortify-string.h +@@ -734,7 +734,8 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp + if (__compiletime_lessthan(p_size, size)) + __read_overflow(); + if (p_size < size) +- fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ, p_size, size, NULL); ++ fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ, p_size, size, ++ __real_kmemdup(p, 0, gfp)); + return __real_kmemdup(p, size, gfp); + } + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 8dfd53b52744a..b09f141321105 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3340,6 +3340,8 @@ void simple_offset_init(struct offset_ctx *octx); + int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry); + void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry); + int simple_offset_empty(struct dentry *dentry); ++int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry); + int simple_offset_rename_exchange(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, +diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h +index 3385a2cc5b099..ac5be38d8aaf0 100644 +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -5302,7 +5302,7 @@ static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data, + info_len += 1; + + return prof->sta_info_len >= info_len && +- fixed + prof->sta_info_len <= len; ++ fixed + prof->sta_info_len - 1 <= len; + } + + /** +diff --git a/include/linux/ksm.h b/include/linux/ksm.h +index 401348e9f92b4..7e2b1de3996ac 100644 +--- a/include/linux/ksm.h ++++ b/include/linux/ksm.h +@@ -59,6 +59,14 @@ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) + return 0; + } + ++static inline int ksm_execve(struct mm_struct *mm) ++{ ++ if (test_bit(MMF_VM_MERGE_ANY, &mm->flags)) ++ return __ksm_enter(mm); ++ ++ return 0; ++} ++ + static inline void ksm_exit(struct mm_struct *mm) + { + if (test_bit(MMF_VM_MERGEABLE, &mm->flags)) +@@ -107,6 +115,11 @@ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) + return 0; + } + ++static inline int ksm_execve(struct mm_struct *mm) ++{ ++ return 0; ++} ++ + static inline void ksm_exit(struct mm_struct *mm) + { + } +diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h +index bf9324a31ae97..80452bd982531 100644 +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -862,6 +862,7 @@ struct mlx5_cmd_work_ent { + void *context; + int idx; + struct completion handling; ++ struct completion slotted; + struct completion done; + struct mlx5_cmd *cmd; + struct work_struct work; +diff --git a/include/linux/numa.h b/include/linux/numa.h +index 915033a757315..1d43371fafd2f 100644 +--- a/include/linux/numa.h ++++ b/include/linux/numa.h +@@ -36,12 +36,7 @@ int memory_add_physaddr_to_nid(u64 start); + int phys_to_target_node(u64 start); + #endif + +-#ifndef numa_fill_memblks +-static inline int __init numa_fill_memblks(u64 start, u64 end) +-{ +- return NUMA_NO_MEMBLK; +-} +-#endif ++int numa_fill_memblks(u64 start, u64 end); + + #else /* !CONFIG_NUMA */ + static inline int numa_nearest_node(int node, unsigned int state) +diff --git a/include/linux/printk.h b/include/linux/printk.h +index 955e31860095e..2fde40cc96778 100644 +--- a/include/linux/printk.h ++++ b/include/linux/printk.h +@@ -126,7 +126,7 @@ struct va_format { + #define no_printk(fmt, ...) \ + ({ \ + if (0) \ +- printk(fmt, ##__VA_ARGS__); \ ++ _printk(fmt, ##__VA_ARGS__); \ + 0; \ + }) + +diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h +index dfa1828cd756a..c0d74f97fd187 100644 +--- a/include/linux/stmmac.h ++++ b/include/linux/stmmac.h +@@ -117,7 +117,6 @@ struct stmmac_axi { + + #define EST_GCL 1024 + struct stmmac_est { +- struct mutex lock; + int enable; + u32 btr_reserve[2]; + u32 btr_offset[2]; +diff --git a/include/net/ax25.h b/include/net/ax25.h +index 0d939e5aee4ec..c2a85fd3f5ea4 100644 +--- a/include/net/ax25.h ++++ b/include/net/ax25.h +@@ -216,7 +216,7 @@ typedef struct { + struct ctl_table; + + typedef struct ax25_dev { +- struct ax25_dev *next; ++ struct list_head list; + + struct net_device *dev; + netdevice_tracker dev_tracker; +@@ -330,7 +330,6 @@ int ax25_addr_size(const ax25_digi *); + void ax25_digi_invert(const ax25_digi *, ax25_digi *); + + /* ax25_dev.c */ +-extern ax25_dev *ax25_dev_list; + extern spinlock_t ax25_dev_lock; + + #if IS_ENABLED(CONFIG_AX25) +diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h +index eaec5d6caa29d..b3228bd6cd6be 100644 +--- a/include/net/bluetooth/bluetooth.h ++++ b/include/net/bluetooth/bluetooth.h +@@ -285,7 +285,7 @@ void bt_err_ratelimited(const char *fmt, ...); + bt_err_ratelimited("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__) + + /* Connection and socket states */ +-enum { ++enum bt_sock_state { + BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ + BT_OPEN, + BT_BOUND, +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index 07198beb3d80b..f187510428ca6 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -33,9 +33,6 @@ + #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) + + #define HCI_LINK_KEY_SIZE 16 +-#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) +- +-#define HCI_MAX_AMP_ASSOC_SIZE 672 + + #define HCI_MAX_CPB_DATA_SIZE 252 + +@@ -71,26 +68,6 @@ + #define HCI_SMD 9 + #define HCI_VIRTIO 10 + +-/* HCI controller types */ +-#define HCI_PRIMARY 0x00 +-#define HCI_AMP 0x01 +- +-/* First BR/EDR Controller shall have ID = 0 */ +-#define AMP_ID_BREDR 0x00 +- +-/* AMP controller types */ +-#define AMP_TYPE_BREDR 0x00 +-#define AMP_TYPE_80211 0x01 +- +-/* AMP controller status */ +-#define AMP_STATUS_POWERED_DOWN 0x00 +-#define AMP_STATUS_BLUETOOTH_ONLY 0x01 +-#define AMP_STATUS_NO_CAPACITY 0x02 +-#define AMP_STATUS_LOW_CAPACITY 0x03 +-#define AMP_STATUS_MEDIUM_CAPACITY 0x04 +-#define AMP_STATUS_HIGH_CAPACITY 0x05 +-#define AMP_STATUS_FULL_CAPACITY 0x06 +- + /* HCI device quirks */ + enum { + /* When this quirk is set, the HCI Reset command is send when +@@ -528,7 +505,6 @@ enum { + #define ESCO_LINK 0x02 + /* Low Energy links do not have defined link type. Use invented one */ + #define LE_LINK 0x80 +-#define AMP_LINK 0x81 + #define ISO_LINK 0x82 + #define INVALID_LINK 0xff + +@@ -944,56 +920,6 @@ struct hci_cp_io_capability_neg_reply { + __u8 reason; + } __packed; + +-#define HCI_OP_CREATE_PHY_LINK 0x0435 +-struct hci_cp_create_phy_link { +- __u8 phy_handle; +- __u8 key_len; +- __u8 key_type; +- __u8 key[HCI_AMP_LINK_KEY_SIZE]; +-} __packed; +- +-#define HCI_OP_ACCEPT_PHY_LINK 0x0436 +-struct hci_cp_accept_phy_link { +- __u8 phy_handle; +- __u8 key_len; +- __u8 key_type; +- __u8 key[HCI_AMP_LINK_KEY_SIZE]; +-} __packed; +- +-#define HCI_OP_DISCONN_PHY_LINK 0x0437 +-struct hci_cp_disconn_phy_link { +- __u8 phy_handle; +- __u8 reason; +-} __packed; +- +-struct ext_flow_spec { +- __u8 id; +- __u8 stype; +- __le16 msdu; +- __le32 sdu_itime; +- __le32 acc_lat; +- __le32 flush_to; +-} __packed; +- +-#define HCI_OP_CREATE_LOGICAL_LINK 0x0438 +-#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439 +-struct hci_cp_create_accept_logical_link { +- __u8 phy_handle; +- struct ext_flow_spec tx_flow_spec; +- struct ext_flow_spec rx_flow_spec; +-} __packed; +- +-#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a +-struct hci_cp_disconn_logical_link { +- __le16 log_handle; +-} __packed; +- +-#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b +-struct hci_cp_logical_link_cancel { +- __u8 phy_handle; +- __u8 flow_spec_id; +-} __packed; +- + #define HCI_OP_ENHANCED_SETUP_SYNC_CONN 0x043d + struct hci_coding_format { + __u8 id; +@@ -1615,46 +1541,6 @@ struct hci_rp_read_enc_key_size { + __u8 key_size; + } __packed; + +-#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409 +-struct hci_rp_read_local_amp_info { +- __u8 status; +- __u8 amp_status; +- __le32 total_bw; +- __le32 max_bw; +- __le32 min_latency; +- __le32 max_pdu; +- __u8 amp_type; +- __le16 pal_cap; +- __le16 max_assoc_size; +- __le32 max_flush_to; +- __le32 be_flush_to; +-} __packed; +- +-#define HCI_OP_READ_LOCAL_AMP_ASSOC 0x140a +-struct hci_cp_read_local_amp_assoc { +- __u8 phy_handle; +- __le16 len_so_far; +- __le16 max_len; +-} __packed; +-struct hci_rp_read_local_amp_assoc { +- __u8 status; +- __u8 phy_handle; +- __le16 rem_len; +- __u8 frag[]; +-} __packed; +- +-#define HCI_OP_WRITE_REMOTE_AMP_ASSOC 0x140b +-struct hci_cp_write_remote_amp_assoc { +- __u8 phy_handle; +- __le16 len_so_far; +- __le16 rem_len; +- __u8 frag[]; +-} __packed; +-struct hci_rp_write_remote_amp_assoc { +- __u8 status; +- __u8 phy_handle; +-} __packed; +- + #define HCI_OP_GET_MWS_TRANSPORT_CONFIG 0x140c + + #define HCI_OP_ENABLE_DUT_MODE 0x1803 +@@ -2035,7 +1921,7 @@ struct hci_cp_le_set_ext_adv_data { + __u8 operation; + __u8 frag_pref; + __u8 length; +- __u8 data[]; ++ __u8 data[] __counted_by(length); + } __packed; + + #define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA 0x2038 +@@ -2044,7 +1930,7 @@ struct hci_cp_le_set_ext_scan_rsp_data { + __u8 operation; + __u8 frag_pref; + __u8 length; +- __u8 data[]; ++ __u8 data[] __counted_by(length); + } __packed; + + #define HCI_OP_LE_SET_EXT_ADV_ENABLE 0x2039 +@@ -2070,7 +1956,7 @@ struct hci_cp_le_set_per_adv_data { + __u8 handle; + __u8 operation; + __u8 length; +- __u8 data[]; ++ __u8 data[] __counted_by(length); + } __packed; + + #define HCI_OP_LE_SET_PER_ADV_ENABLE 0x2040 +@@ -2171,7 +2057,7 @@ struct hci_cis { + + struct hci_cp_le_create_cis { + __u8 num_cis; +- struct hci_cis cis[]; ++ struct hci_cis cis[] __counted_by(num_cis); + } __packed; + + #define HCI_OP_LE_REMOVE_CIG 0x2065 +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index b1c8489ff93e4..5277c6d5134ca 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -126,7 +126,6 @@ enum suspended_state { + struct hci_conn_hash { + struct list_head list; + unsigned int acl_num; +- unsigned int amp_num; + unsigned int sco_num; + unsigned int iso_num; + unsigned int le_num; +@@ -247,6 +246,7 @@ struct adv_info { + bool periodic; + __u8 mesh; + __u8 instance; ++ __u8 handle; + __u32 flags; + __u16 timeout; + __u16 remaining_time; +@@ -341,14 +341,6 @@ struct adv_monitor { + /* Default authenticated payload timeout 30s */ + #define DEFAULT_AUTH_PAYLOAD_TIMEOUT 0x0bb8 + +-struct amp_assoc { +- __u16 len; +- __u16 offset; +- __u16 rem_len; +- __u16 len_so_far; +- __u8 data[HCI_MAX_AMP_ASSOC_SIZE]; +-}; +- + #define HCI_MAX_PAGES 3 + + struct hci_dev { +@@ -361,7 +353,6 @@ struct hci_dev { + unsigned long flags; + __u16 id; + __u8 bus; +- __u8 dev_type; + bdaddr_t bdaddr; + bdaddr_t setup_addr; + bdaddr_t public_addr; +@@ -467,21 +458,6 @@ struct hci_dev { + __u16 sniff_min_interval; + __u16 sniff_max_interval; + +- __u8 amp_status; +- __u32 amp_total_bw; +- __u32 amp_max_bw; +- __u32 amp_min_latency; +- __u32 amp_max_pdu; +- __u8 amp_type; +- __u16 amp_pal_cap; +- __u16 amp_assoc_size; +- __u32 amp_max_flush_to; +- __u32 amp_be_flush_to; +- +- struct amp_assoc loc_assoc; +- +- __u8 flow_ctl_mode; +- + unsigned int auto_accept_delay; + + unsigned long quirks; +@@ -501,11 +477,6 @@ struct hci_dev { + unsigned int le_pkts; + unsigned int iso_pkts; + +- __u16 block_len; +- __u16 block_mtu; +- __u16 num_blocks; +- __u16 block_cnt; +- + unsigned long acl_last_tx; + unsigned long sco_last_tx; + unsigned long le_last_tx; +@@ -778,7 +749,6 @@ struct hci_conn { + void *l2cap_data; + void *sco_data; + void *iso_data; +- struct amp_mgr *amp_mgr; + + struct list_head link_list; + struct hci_conn *parent; +@@ -805,7 +775,6 @@ struct hci_chan { + struct sk_buff_head data_q; + unsigned int sent; + __u8 state; +- bool amp; + }; + + struct hci_conn_params { +@@ -1014,9 +983,6 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) + case ACL_LINK: + h->acl_num++; + break; +- case AMP_LINK: +- h->amp_num++; +- break; + case LE_LINK: + h->le_num++; + if (c->role == HCI_ROLE_SLAVE) +@@ -1043,9 +1009,6 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) + case ACL_LINK: + h->acl_num--; + break; +- case AMP_LINK: +- h->amp_num--; +- break; + case LE_LINK: + h->le_num--; + if (c->role == HCI_ROLE_SLAVE) +@@ -1067,8 +1030,6 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) + switch (type) { + case ACL_LINK: + return h->acl_num; +- case AMP_LINK: +- return h->amp_num; + case LE_LINK: + return h->le_num; + case SCO_LINK: +@@ -1085,7 +1046,7 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev) + { + struct hci_conn_hash *c = &hdev->conn_hash; + +- return c->acl_num + c->amp_num + c->sco_num + c->le_num + c->iso_num; ++ return c->acl_num + c->sco_num + c->le_num + c->iso_num; + } + + static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn) +@@ -1611,10 +1572,6 @@ static inline void hci_conn_drop(struct hci_conn *conn) + } + break; + +- case AMP_LINK: +- timeo = conn->disc_timeout; +- break; +- + default: + timeo = 0; + break; +diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h +index a4278aa618ab1..3434cfc26b6af 100644 +--- a/include/net/bluetooth/l2cap.h ++++ b/include/net/bluetooth/l2cap.h +@@ -548,6 +548,9 @@ struct l2cap_chan { + __u16 tx_credits; + __u16 rx_credits; + ++ /* estimated available receive buffer space or -1 if unknown */ ++ ssize_t rx_avail; ++ + __u8 tx_state; + __u8 rx_state; + +@@ -682,10 +685,15 @@ struct l2cap_user { + /* ----- L2CAP socket info ----- */ + #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) + ++struct l2cap_rx_busy { ++ struct list_head list; ++ struct sk_buff *skb; ++}; ++ + struct l2cap_pinfo { + struct bt_sock bt; + struct l2cap_chan *chan; +- struct sk_buff *rx_busy_skb; ++ struct list_head rx_busy; + }; + + enum { +@@ -943,6 +951,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, + int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu); + int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len); + void l2cap_chan_busy(struct l2cap_chan *chan, int busy); ++void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail); + int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator); + void l2cap_chan_set_defaults(struct l2cap_chan *chan); + int l2cap_ertm_init(struct l2cap_chan *chan); +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 6ae35199d3b3c..2bcf30381d75f 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1539,11 +1539,10 @@ static inline int tcp_space_from_win(const struct sock *sk, int win) + return __tcp_space_from_win(tcp_sk(sk)->scaling_ratio, win); + } + +-/* Assume a conservative default of 1200 bytes of payload per 4K page. ++/* Assume a 50% default for skb->len/skb->truesize ratio. + * This may be adjusted later in tcp_measure_rcv_mss(). + */ +-#define TCP_DEFAULT_SCALING_RATIO ((1200 << TCP_RMEM_TO_WIN_SCALE) / \ +- SKB_TRUESIZE(4096)) ++#define TCP_DEFAULT_SCALING_RATIO (1 << (TCP_RMEM_TO_WIN_SCALE - 1)) + + static inline void tcp_scaling_ratio_init(struct sock *sk) + { +diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h +index 4eed9028bb119..517015ef36a84 100644 +--- a/include/trace/events/asoc.h ++++ b/include/trace/events/asoc.h +@@ -12,6 +12,8 @@ + #define DAPM_DIRECT "(direct)" + #define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-") + ++TRACE_DEFINE_ENUM(SND_SOC_DAPM_DIR_OUT); ++ + struct snd_soc_jack; + struct snd_soc_card; + struct snd_soc_dapm_widget; +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 3c42b9f1bada3..bcd84985faf48 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -7150,7 +7150,7 @@ struct bpf_fib_lookup { + + /* output: MTU value */ + __u16 mtu_result; +- }; ++ } __attribute__((packed, aligned(2))); + /* input: L3 device index for lookup + * output: device index from FIB lookup + */ +diff --git a/include/uapi/linux/virtio_bt.h b/include/uapi/linux/virtio_bt.h +index af798f4c96804..3cc7d633456b6 100644 +--- a/include/uapi/linux/virtio_bt.h ++++ b/include/uapi/linux/virtio_bt.h +@@ -13,7 +13,6 @@ + + enum virtio_bt_config_type { + VIRTIO_BT_CONFIG_TYPE_PRIMARY = 0, +- VIRTIO_BT_CONFIG_TYPE_AMP = 1, + }; + + enum virtio_bt_config_vendor { +diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c +index 522196dfb0ff5..318ed067dbf64 100644 +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -564,10 +564,7 @@ static void io_worker_handle_work(struct io_wq_acct *acct, + * clear the stalled flag. + */ + work = io_get_next_work(acct, worker); +- raw_spin_unlock(&acct->lock); + if (work) { +- __io_worker_busy(wq, worker); +- + /* + * Make sure cancelation can find this, even before + * it becomes the active work. That avoids a window +@@ -578,9 +575,15 @@ static void io_worker_handle_work(struct io_wq_acct *acct, + raw_spin_lock(&worker->lock); + worker->next_work = work; + raw_spin_unlock(&worker->lock); +- } else { +- break; + } ++ ++ raw_spin_unlock(&acct->lock); ++ ++ if (!work) ++ break; ++ ++ __io_worker_busy(wq, worker); ++ + io_assign_current_work(worker, work); + __set_current_state(TASK_RUNNING); + +diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h +index 6426ee382276b..03e52094630ac 100644 +--- a/io_uring/io_uring.h ++++ b/io_uring/io_uring.h +@@ -340,7 +340,7 @@ static inline int io_run_task_work(void) + + static inline bool io_task_work_pending(struct io_ring_ctx *ctx) + { +- return task_work_pending(current) || !wq_list_empty(&ctx->work_llist); ++ return task_work_pending(current) || !llist_empty(&ctx->work_llist); + } + + static inline void io_tw_lock(struct io_ring_ctx *ctx, struct io_tw_state *ts) +diff --git a/io_uring/net.c b/io_uring/net.c +index 4afb475d41974..3896e6220d0bf 100644 +--- a/io_uring/net.c ++++ b/io_uring/net.c +@@ -1041,6 +1041,7 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + struct io_kiocb *notif; + + zc->done_io = 0; ++ req->flags |= REQ_F_POLL_NO_LAZY; + + if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3))) + return -EINVAL; +diff --git a/io_uring/nop.c b/io_uring/nop.c +index d956599a3c1b8..1a4e312dfe510 100644 +--- a/io_uring/nop.c ++++ b/io_uring/nop.c +@@ -12,6 +12,8 @@ + + int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + { ++ if (READ_ONCE(sqe->rw_flags)) ++ return -EINVAL; + return 0; + } + +diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c +index 3983708cef5b4..158ab09c605ba 100644 +--- a/io_uring/sqpoll.c ++++ b/io_uring/sqpoll.c +@@ -238,11 +238,13 @@ static unsigned int io_sq_tw(struct llist_node **retry_list, int max_entries) + if (*retry_list) { + *retry_list = io_handle_tw_list(*retry_list, &count, max_entries); + if (count >= max_entries) +- return count; ++ goto out; + max_entries -= count; + } +- + *retry_list = tctx_task_work_run(tctx, max_entries, &count); ++out: ++ if (task_work_pending(current)) ++ task_work_run(); + return count; + } + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index c287925471f68..cb61d8880dbe0 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -3985,6 +3985,11 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog, + * check permissions at attach time. + */ + return -EPERM; ++ ++ ptype = attach_type_to_prog_type(attach_type); ++ if (prog->type != ptype) ++ return -EINVAL; ++ + return prog->enforce_expected_attach_type && + prog->expected_attach_type != attach_type ? + -EINVAL : 0; +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index cb7ad1f795e18..2c90b1eb12e2c 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2359,6 +2359,8 @@ static void mark_btf_ld_reg(struct bpf_verifier_env *env, + regs[regno].type = PTR_TO_BTF_ID | flag; + regs[regno].btf = btf; + regs[regno].btf_id = btf_id; ++ if (type_may_be_null(flag)) ++ regs[regno].id = ++env->id_gen; + } + + #define DEF_NOT_SUBREG (0) +@@ -3615,7 +3617,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, + * sreg needs precision before this insn + */ + bt_clear_reg(bt, dreg); +- bt_set_reg(bt, sreg); ++ if (sreg != BPF_REG_FP) ++ bt_set_reg(bt, sreg); + } else { + /* dreg = K + * dreg needs precision after this insn. +@@ -3631,7 +3634,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, + * both dreg and sreg need precision + * before this insn + */ +- bt_set_reg(bt, sreg); ++ if (sreg != BPF_REG_FP) ++ bt_set_reg(bt, sreg); + } /* else dreg += K + * dreg still needs precision before this insn + */ +@@ -5386,8 +5390,6 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno, + */ + mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID, kptr_field->kptr.btf, + kptr_field->kptr.btf_id, btf_ld_kptr_type(env, kptr_field)); +- /* For mark_ptr_or_null_reg */ +- val_reg->id = ++env->id_gen; + } else if (class == BPF_STX) { + val_reg = reg_state(env, value_regno); + if (!register_is_null(val_reg) && +@@ -5705,7 +5707,8 @@ static bool is_trusted_reg(const struct bpf_reg_state *reg) + return true; + + /* Types listed in the reg2btf_ids are always trusted */ +- if (reg2btf_ids[base_type(reg->type)]) ++ if (reg2btf_ids[base_type(reg->type)] && ++ !bpf_type_has_unsafe_modifiers(reg->type)) + return true; + + /* If a register is not referenced, it is trusted if it has the +@@ -6325,6 +6328,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, + #define BTF_TYPE_SAFE_RCU(__type) __PASTE(__type, __safe_rcu) + #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) + #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) ++#define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) + + /* + * Allow list few fields as RCU trusted or full trusted. +@@ -6388,7 +6392,7 @@ BTF_TYPE_SAFE_TRUSTED(struct dentry) { + struct inode *d_inode; + }; + +-BTF_TYPE_SAFE_TRUSTED(struct socket) { ++BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket) { + struct sock *sk; + }; + +@@ -6423,11 +6427,20 @@ static bool type_is_trusted(struct bpf_verifier_env *env, + BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct linux_binprm)); + BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct file)); + BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct dentry)); +- BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct socket)); + + return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, "__safe_trusted"); + } + ++static bool type_is_trusted_or_null(struct bpf_verifier_env *env, ++ struct bpf_reg_state *reg, ++ const char *field_name, u32 btf_id) ++{ ++ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket)); ++ ++ return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, ++ "__safe_trusted_or_null"); ++} ++ + static int check_ptr_to_btf_access(struct bpf_verifier_env *env, + struct bpf_reg_state *regs, + int regno, int off, int size, +@@ -6536,6 +6549,8 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, + */ + if (type_is_trusted(env, reg, field_name, btf_id)) { + flag |= PTR_TRUSTED; ++ } else if (type_is_trusted_or_null(env, reg, field_name, btf_id)) { ++ flag |= PTR_TRUSTED | PTR_MAYBE_NULL; + } else if (in_rcu_cs(env) && !type_may_be_null(reg->type)) { + if (type_is_rcu(env, reg, field_name, btf_id)) { + /* ignore __rcu tag and mark it MEM_RCU */ +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index 4237c8748715d..da24187c4e025 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -2948,7 +2948,7 @@ bool current_cpuset_is_being_rebound(void) + static int update_relax_domain_level(struct cpuset *cs, s64 val) + { + #ifdef CONFIG_SMP +- if (val < -1 || val >= sched_domain_level_max) ++ if (val < -1 || val > sched_domain_level_max + 1) + return -EINVAL; + #endif + +diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h +index 147b5945d67a0..2a453de9f3d95 100644 +--- a/kernel/rcu/tasks.h ++++ b/kernel/rcu/tasks.h +@@ -1994,7 +1994,7 @@ void show_rcu_tasks_trace_gp_kthread(void) + { + char buf[64]; + +- sprintf(buf, "N%lu h:%lu/%lu/%lu", ++ snprintf(buf, sizeof(buf), "N%lu h:%lu/%lu/%lu", + data_race(n_trc_holdouts), + data_race(n_heavy_reader_ofl_updates), + data_race(n_heavy_reader_updates), +diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h +index 5d666428546b0..b5ec62b2d850a 100644 +--- a/kernel/rcu/tree_stall.h ++++ b/kernel/rcu/tree_stall.h +@@ -504,7 +504,8 @@ static void print_cpu_stall_info(int cpu) + rcu_dynticks_in_eqs(rcu_dynticks_snap(cpu)); + rcuc_starved = rcu_is_rcuc_kthread_starving(rdp, &j); + if (rcuc_starved) +- sprintf(buf, " rcuc=%ld jiffies(starved)", j); ++ // Print signed value, as negative values indicate a probable bug. ++ snprintf(buf, sizeof(buf), " rcuc=%ld jiffies(starved)", j); + pr_err("\t%d-%c%c%c%c: (%lu %s) idle=%04x/%ld/%#lx softirq=%u/%u fqs=%ld%s%s\n", + cpu, + "O."[!!cpu_online(cpu)], +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 7019a40457a6d..d211d40a2edc9 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -11402,7 +11402,7 @@ static ssize_t cpu_max_write(struct kernfs_open_file *of, + { + struct task_group *tg = css_tg(of_css(of)); + u64 period = tg_get_cfs_period(tg); +- u64 burst = tg_get_cfs_burst(tg); ++ u64 burst = tg->cfs_bandwidth.burst; + u64 quota; + int ret; + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index c62805dbd6088..213c94d027a4c 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -6675,22 +6675,42 @@ static inline void hrtick_update(struct rq *rq) + #ifdef CONFIG_SMP + static inline bool cpu_overutilized(int cpu) + { +- unsigned long rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN); +- unsigned long rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX); ++ unsigned long rq_util_min, rq_util_max; ++ ++ if (!sched_energy_enabled()) ++ return false; ++ ++ rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN); ++ rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX); + + /* Return true only if the utilization doesn't fit CPU's capacity */ + return !util_fits_cpu(cpu_util_cfs(cpu), rq_util_min, rq_util_max, cpu); + } + +-static inline void update_overutilized_status(struct rq *rq) ++static inline void set_rd_overutilized_status(struct root_domain *rd, ++ unsigned int status) + { +- if (!READ_ONCE(rq->rd->overutilized) && cpu_overutilized(rq->cpu)) { +- WRITE_ONCE(rq->rd->overutilized, SG_OVERUTILIZED); +- trace_sched_overutilized_tp(rq->rd, SG_OVERUTILIZED); +- } ++ if (!sched_energy_enabled()) ++ return; ++ ++ WRITE_ONCE(rd->overutilized, status); ++ trace_sched_overutilized_tp(rd, !!status); ++} ++ ++static inline void check_update_overutilized_status(struct rq *rq) ++{ ++ /* ++ * overutilized field is used for load balancing decisions only ++ * if energy aware scheduler is being used ++ */ ++ if (!sched_energy_enabled()) ++ return; ++ ++ if (!READ_ONCE(rq->rd->overutilized) && cpu_overutilized(rq->cpu)) ++ set_rd_overutilized_status(rq->rd, SG_OVERUTILIZED); + } + #else +-static inline void update_overutilized_status(struct rq *rq) { } ++static inline void check_update_overutilized_status(struct rq *rq) { } + #endif + + /* Runqueue only has SCHED_IDLE tasks enqueued */ +@@ -6791,7 +6811,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) + * and the following generally works well enough in practice. + */ + if (!task_new) +- update_overutilized_status(rq); ++ check_update_overutilized_status(rq); + + enqueue_throttle: + assert_list_leaf_cfs_rq(rq); +@@ -10608,19 +10628,14 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd + env->fbq_type = fbq_classify_group(&sds->busiest_stat); + + if (!env->sd->parent) { +- struct root_domain *rd = env->dst_rq->rd; +- + /* update overload indicator if we are at root domain */ +- WRITE_ONCE(rd->overload, sg_status & SG_OVERLOAD); ++ WRITE_ONCE(env->dst_rq->rd->overload, sg_status & SG_OVERLOAD); + + /* Update over-utilization (tipping point, U >= 0) indicator */ +- WRITE_ONCE(rd->overutilized, sg_status & SG_OVERUTILIZED); +- trace_sched_overutilized_tp(rd, sg_status & SG_OVERUTILIZED); ++ set_rd_overutilized_status(env->dst_rq->rd, ++ sg_status & SG_OVERUTILIZED); + } else if (sg_status & SG_OVERUTILIZED) { +- struct root_domain *rd = env->dst_rq->rd; +- +- WRITE_ONCE(rd->overutilized, SG_OVERUTILIZED); +- trace_sched_overutilized_tp(rd, SG_OVERUTILIZED); ++ set_rd_overutilized_status(env->dst_rq->rd, SG_OVERUTILIZED); + } + + update_idle_cpu_scan(env, sum_util); +@@ -12621,7 +12636,7 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued) + task_tick_numa(rq, curr); + + update_misfit_status(curr, rq); +- update_overutilized_status(task_rq(curr)); ++ check_update_overutilized_status(task_rq(curr)); + + task_tick_core(rq, curr); + } +diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c +index 99ea5986038ce..3127c9b30af18 100644 +--- a/kernel/sched/topology.c ++++ b/kernel/sched/topology.c +@@ -1468,7 +1468,7 @@ static void set_domain_attribute(struct sched_domain *sd, + } else + request = attr->relax_domain_level; + +- if (sd->level > request) { ++ if (sd->level >= request) { + /* Turn off idle balance on this domain: */ + sd->flags &= ~(SD_BALANCE_WAKE|SD_BALANCE_NEWIDLE); + } +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index da1710499698b..1e12df9bb531b 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -1595,12 +1595,15 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end) + unsigned long ftrace_location_range(unsigned long start, unsigned long end) + { + struct dyn_ftrace *rec; ++ unsigned long ip = 0; + ++ rcu_read_lock(); + rec = lookup_rec(start, end); + if (rec) +- return rec->ip; ++ ip = rec->ip; ++ rcu_read_unlock(); + +- return 0; ++ return ip; + } + + /** +@@ -1614,25 +1617,22 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end) + */ + unsigned long ftrace_location(unsigned long ip) + { +- struct dyn_ftrace *rec; ++ unsigned long loc; + unsigned long offset; + unsigned long size; + +- rec = lookup_rec(ip, ip); +- if (!rec) { ++ loc = ftrace_location_range(ip, ip); ++ if (!loc) { + if (!kallsyms_lookup_size_offset(ip, &size, &offset)) + goto out; + + /* map sym+0 to __fentry__ */ + if (!offset) +- rec = lookup_rec(ip, ip + size - 1); ++ loc = ftrace_location_range(ip, ip + size - 1); + } + +- if (rec) +- return rec->ip; +- + out: +- return 0; ++ return loc; + } + + /** +@@ -6596,6 +6596,8 @@ static int ftrace_process_locs(struct module *mod, + /* We should have used all pages unless we skipped some */ + if (pg_unuse) { + WARN_ON(!skipped); ++ /* Need to synchronize with ftrace_location_range() */ ++ synchronize_rcu(); + ftrace_free_pages(pg_unuse); + } + return ret; +@@ -6809,6 +6811,9 @@ void ftrace_release_mod(struct module *mod) + out_unlock: + mutex_unlock(&ftrace_lock); + ++ /* Need to synchronize with ftrace_location_range() */ ++ if (tmp_page) ++ synchronize_rcu(); + for (pg = tmp_page; pg; pg = tmp_page) { + + /* Needs to be called outside of ftrace_lock */ +@@ -7142,6 +7147,7 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) + unsigned long start = (unsigned long)(start_ptr); + unsigned long end = (unsigned long)(end_ptr); + struct ftrace_page **last_pg = &ftrace_pages_start; ++ struct ftrace_page *tmp_page = NULL; + struct ftrace_page *pg; + struct dyn_ftrace *rec; + struct dyn_ftrace key; +@@ -7183,12 +7189,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) + ftrace_update_tot_cnt--; + if (!pg->index) { + *last_pg = pg->next; +- if (pg->records) { +- free_pages((unsigned long)pg->records, pg->order); +- ftrace_number_of_pages -= 1 << pg->order; +- } +- ftrace_number_of_groups--; +- kfree(pg); ++ pg->next = tmp_page; ++ tmp_page = pg; + pg = container_of(last_pg, struct ftrace_page, next); + if (!(*last_pg)) + ftrace_pages = pg; +@@ -7205,6 +7207,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) + clear_func_from_hashes(func); + kfree(func); + } ++ /* Need to synchronize with ftrace_location_range() */ ++ if (tmp_page) { ++ synchronize_rcu(); ++ ftrace_free_pages(tmp_page); ++ } + } + + void __init ftrace_free_init_mem(void) +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 6511dc3a00da8..54887f4c35b2e 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -1449,6 +1449,11 @@ static void rb_check_bpage(struct ring_buffer_per_cpu *cpu_buffer, + * + * As a safety measure we check to make sure the data pages have not + * been corrupted. ++ * ++ * Callers of this function need to guarantee that the list of pages doesn't get ++ * modified during the check. In particular, if it's possible that the function ++ * is invoked with concurrent readers which can swap in a new reader page then ++ * the caller should take cpu_buffer->reader_lock. + */ + static void rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer) + { +@@ -2200,8 +2205,12 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size, + */ + synchronize_rcu(); + for_each_buffer_cpu(buffer, cpu) { ++ unsigned long flags; ++ + cpu_buffer = buffer->buffers[cpu]; ++ raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags); + rb_check_pages(cpu_buffer); ++ raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); + } + atomic_dec(&buffer->record_disabled); + } +diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c +index 70d428c394b68..82b191f33a28f 100644 +--- a/kernel/trace/trace_events_user.c ++++ b/kernel/trace/trace_events_user.c +@@ -1989,6 +1989,80 @@ static int user_event_set_tp_name(struct user_event *user) + return 0; + } + ++/* ++ * Counts how many ';' without a trailing space are in the args. ++ */ ++static int count_semis_no_space(char *args) ++{ ++ int count = 0; ++ ++ while ((args = strchr(args, ';'))) { ++ args++; ++ ++ if (!isspace(*args)) ++ count++; ++ } ++ ++ return count; ++} ++ ++/* ++ * Copies the arguments while ensuring all ';' have a trailing space. ++ */ ++static char *insert_space_after_semis(char *args, int count) ++{ ++ char *fixed, *pos; ++ int len; ++ ++ len = strlen(args) + count; ++ fixed = kmalloc(len + 1, GFP_KERNEL); ++ ++ if (!fixed) ++ return NULL; ++ ++ pos = fixed; ++ ++ /* Insert a space after ';' if there is no trailing space. */ ++ while (*args) { ++ *pos = *args++; ++ ++ if (*pos++ == ';' && !isspace(*args)) ++ *pos++ = ' '; ++ } ++ ++ *pos = '\0'; ++ ++ return fixed; ++} ++ ++static char **user_event_argv_split(char *args, int *argc) ++{ ++ char **split; ++ char *fixed; ++ int count; ++ ++ /* Count how many ';' without a trailing space */ ++ count = count_semis_no_space(args); ++ ++ /* No fixup is required */ ++ if (!count) ++ return argv_split(GFP_KERNEL, args, argc); ++ ++ /* We must fixup 'field;field' to 'field; field' */ ++ fixed = insert_space_after_semis(args, count); ++ ++ if (!fixed) ++ return NULL; ++ ++ /* We do a normal split afterwards */ ++ split = argv_split(GFP_KERNEL, fixed, argc); ++ ++ /* We can free since argv_split makes a copy */ ++ kfree(fixed); ++ ++ return split; ++} ++ + /* + * Parses the event name, arguments and flags then registers if successful. + * The name buffer lifetime is owned by this method for success cases only. +@@ -2012,7 +2086,7 @@ static int user_event_parse(struct user_event_group *group, char *name, + return -EPERM; + + if (args) { +- argv = argv_split(GFP_KERNEL, args, &argc); ++ argv = user_event_argv_split(args, &argc); + + if (!argv) + return -ENOMEM; +diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c +index 493ec02dd5b32..fdba0eaf19a59 100644 +--- a/lib/fortify_kunit.c ++++ b/lib/fortify_kunit.c +@@ -267,28 +267,28 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(vmalloc) + \ + checker((expected_pages) * PAGE_SIZE, \ + kvmalloc((alloc_pages) * PAGE_SIZE, gfp), \ +- vfree(p)); \ ++ kvfree(p)); \ + checker((expected_pages) * PAGE_SIZE, \ + kvmalloc_node((alloc_pages) * PAGE_SIZE, gfp, NUMA_NO_NODE), \ +- vfree(p)); \ ++ kvfree(p)); \ + checker((expected_pages) * PAGE_SIZE, \ + kvzalloc((alloc_pages) * PAGE_SIZE, gfp), \ +- vfree(p)); \ ++ kvfree(p)); \ + checker((expected_pages) * PAGE_SIZE, \ + kvzalloc_node((alloc_pages) * PAGE_SIZE, gfp, NUMA_NO_NODE), \ +- vfree(p)); \ ++ kvfree(p)); \ + checker((expected_pages) * PAGE_SIZE, \ + kvcalloc(1, (alloc_pages) * PAGE_SIZE, gfp), \ +- vfree(p)); \ ++ kvfree(p)); \ + checker((expected_pages) * PAGE_SIZE, \ + kvcalloc((alloc_pages) * PAGE_SIZE, 1, gfp), \ +- vfree(p)); \ ++ kvfree(p)); \ + checker((expected_pages) * PAGE_SIZE, \ + kvmalloc_array(1, (alloc_pages) * PAGE_SIZE, gfp), \ +- vfree(p)); \ ++ kvfree(p)); \ + checker((expected_pages) * PAGE_SIZE, \ + kvmalloc_array((alloc_pages) * PAGE_SIZE, 1, gfp), \ +- vfree(p)); \ ++ kvfree(p)); \ + \ + prev_size = (expected_pages) * PAGE_SIZE; \ + orig = kvmalloc(prev_size, gfp); \ +@@ -917,19 +917,19 @@ static void kmemdup_test(struct kunit *test) + + /* Out of bounds by 1 byte. */ + copy = kmemdup(src, len + 1, GFP_KERNEL); +- KUNIT_EXPECT_NULL(test, copy); ++ KUNIT_EXPECT_PTR_EQ(test, copy, ZERO_SIZE_PTR); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1); + kfree(copy); + + /* Way out of bounds. */ + copy = kmemdup(src, len * 2, GFP_KERNEL); +- KUNIT_EXPECT_NULL(test, copy); ++ KUNIT_EXPECT_PTR_EQ(test, copy, ZERO_SIZE_PTR); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2); + kfree(copy); + + /* Starting offset causing out of bounds. */ + copy = kmemdup(src + 1, len, GFP_KERNEL); +- KUNIT_EXPECT_NULL(test, copy); ++ KUNIT_EXPECT_PTR_EQ(test, copy, ZERO_SIZE_PTR); + KUNIT_EXPECT_EQ(test, fortify_read_overflows, 3); + kfree(copy); + } +diff --git a/lib/kunit/device.c b/lib/kunit/device.c +index abc603730b8ea..25c81ed465fb7 100644 +--- a/lib/kunit/device.c ++++ b/lib/kunit/device.c +@@ -51,7 +51,7 @@ int kunit_bus_init(void) + + error = bus_register(&kunit_bus_type); + if (error) +- bus_unregister(&kunit_bus_type); ++ root_device_unregister(kunit_bus_device); + return error; + } + +diff --git a/lib/kunit/test.c b/lib/kunit/test.c +index 1d1475578515c..b8514dbb337c0 100644 +--- a/lib/kunit/test.c ++++ b/lib/kunit/test.c +@@ -712,6 +712,9 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_ + { + unsigned int i; + ++ if (num_suites == 0) ++ return 0; ++ + if (!kunit_enabled() && num_suites > 0) { + pr_info("kunit: disabled\n"); + return 0; +diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c +index f7825991d576a..d9d1df28cc52e 100644 +--- a/lib/kunit/try-catch.c ++++ b/lib/kunit/try-catch.c +@@ -11,6 +11,7 @@ + #include <linux/completion.h> + #include <linux/kernel.h> + #include <linux/kthread.h> ++#include <linux/sched/task.h> + + #include "try-catch-impl.h" + +@@ -65,13 +66,14 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context) + try_catch->context = context; + try_catch->try_completion = &try_completion; + try_catch->try_result = 0; +- task_struct = kthread_run(kunit_generic_run_threadfn_adapter, +- try_catch, +- "kunit_try_catch_thread"); ++ task_struct = kthread_create(kunit_generic_run_threadfn_adapter, ++ try_catch, "kunit_try_catch_thread"); + if (IS_ERR(task_struct)) { + try_catch->catch(try_catch->context); + return; + } ++ get_task_struct(task_struct); ++ wake_up_process(task_struct); + + time_remaining = wait_for_completion_timeout(&try_completion, + kunit_test_timeout()); +@@ -81,6 +83,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context) + kthread_stop(task_struct); + } + ++ put_task_struct(task_struct); + exit_code = try_catch->try_result; + + if (!exit_code) +diff --git a/lib/slub_kunit.c b/lib/slub_kunit.c +index d4a3730b08fa7..4ce9604388069 100644 +--- a/lib/slub_kunit.c ++++ b/lib/slub_kunit.c +@@ -55,7 +55,7 @@ static void test_next_pointer(struct kunit *test) + + ptr_addr = (unsigned long *)(p + s->offset); + tmp = *ptr_addr; +- p[s->offset] = 0x12; ++ p[s->offset] = ~p[s->offset]; + + /* + * Expecting three errors. +diff --git a/lib/test_hmm.c b/lib/test_hmm.c +index 717dcb8301273..b823ba7cb6a15 100644 +--- a/lib/test_hmm.c ++++ b/lib/test_hmm.c +@@ -1226,8 +1226,8 @@ static void dmirror_device_evict_chunk(struct dmirror_chunk *chunk) + unsigned long *src_pfns; + unsigned long *dst_pfns; + +- src_pfns = kcalloc(npages, sizeof(*src_pfns), GFP_KERNEL); +- dst_pfns = kcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL); ++ src_pfns = kvcalloc(npages, sizeof(*src_pfns), GFP_KERNEL | __GFP_NOFAIL); ++ dst_pfns = kvcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL); + + migrate_device_range(src_pfns, start_pfn, npages); + for (i = 0; i < npages; i++) { +@@ -1250,8 +1250,8 @@ static void dmirror_device_evict_chunk(struct dmirror_chunk *chunk) + } + migrate_device_pages(src_pfns, dst_pfns, npages); + migrate_device_finalize(src_pfns, dst_pfns, npages); +- kfree(src_pfns); +- kfree(dst_pfns); ++ kvfree(src_pfns); ++ kvfree(dst_pfns); + } + + /* Removes free pages from the free list so they can't be re-allocated */ +diff --git a/mm/shmem.c b/mm/shmem.c +index 94ab99b6b574a..1f84a41aeb850 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -3467,8 +3467,7 @@ static int shmem_rename2(struct mnt_idmap *idmap, + return error; + } + +- simple_offset_remove(shmem_get_offset_ctx(old_dir), old_dentry); +- error = simple_offset_add(shmem_get_offset_ctx(new_dir), old_dentry); ++ error = simple_offset_rename(old_dir, old_dentry, new_dir, new_dentry); + if (error) + return error; + +diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c +index 3c3539c573e7f..829f7b1089fc6 100644 +--- a/mm/userfaultfd.c ++++ b/mm/userfaultfd.c +@@ -316,6 +316,38 @@ static int mfill_atomic_pte_copy(pmd_t *dst_pmd, + goto out; + } + ++static int mfill_atomic_pte_zeroed_folio(pmd_t *dst_pmd, ++ struct vm_area_struct *dst_vma, ++ unsigned long dst_addr) ++{ ++ struct folio *folio; ++ int ret = -ENOMEM; ++ ++ folio = vma_alloc_zeroed_movable_folio(dst_vma, dst_addr); ++ if (!folio) ++ return ret; ++ ++ if (mem_cgroup_charge(folio, dst_vma->vm_mm, GFP_KERNEL)) ++ goto out_put; ++ ++ /* ++ * The memory barrier inside __folio_mark_uptodate makes sure that ++ * zeroing out the folio become visible before mapping the page ++ * using set_pte_at(). See do_anonymous_page(). ++ */ ++ __folio_mark_uptodate(folio); ++ ++ ret = mfill_atomic_install_pte(dst_pmd, dst_vma, dst_addr, ++ &folio->page, true, 0); ++ if (ret) ++ goto out_put; ++ ++ return 0; ++out_put: ++ folio_put(folio); ++ return ret; ++} ++ + static int mfill_atomic_pte_zeropage(pmd_t *dst_pmd, + struct vm_area_struct *dst_vma, + unsigned long dst_addr) +@@ -324,6 +356,9 @@ static int mfill_atomic_pte_zeropage(pmd_t *dst_pmd, + spinlock_t *ptl; + int ret; + ++ if (mm_forbids_zeropage(dst_vma->vm_mm)) ++ return mfill_atomic_pte_zeroed_folio(dst_pmd, dst_vma, dst_addr); ++ + _dst_pte = pte_mkspecial(pfn_pte(my_zero_pfn(dst_addr), + dst_vma->vm_page_prot)); + ret = -EAGAIN; +diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c +index 282ec581c0720..c9d55b99a7a57 100644 +--- a/net/ax25/ax25_dev.c ++++ b/net/ax25/ax25_dev.c +@@ -22,11 +22,12 @@ + #include <net/sock.h> + #include <linux/uaccess.h> + #include <linux/fcntl.h> ++#include <linux/list.h> + #include <linux/mm.h> + #include <linux/interrupt.h> + #include <linux/init.h> + +-ax25_dev *ax25_dev_list; ++static LIST_HEAD(ax25_dev_list); + DEFINE_SPINLOCK(ax25_dev_lock); + + ax25_dev *ax25_addr_ax25dev(ax25_address *addr) +@@ -34,10 +35,11 @@ ax25_dev *ax25_addr_ax25dev(ax25_address *addr) + ax25_dev *ax25_dev, *res = NULL; + + spin_lock_bh(&ax25_dev_lock); +- for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) ++ list_for_each_entry(ax25_dev, &ax25_dev_list, list) + if (ax25cmp(addr, (const ax25_address *)ax25_dev->dev->dev_addr) == 0) { + res = ax25_dev; + ax25_dev_hold(ax25_dev); ++ break; + } + spin_unlock_bh(&ax25_dev_lock); + +@@ -59,7 +61,6 @@ void ax25_dev_device_up(struct net_device *dev) + } + + refcount_set(&ax25_dev->refcount, 1); +- dev->ax25_ptr = ax25_dev; + ax25_dev->dev = dev; + netdev_hold(dev, &ax25_dev->dev_tracker, GFP_KERNEL); + ax25_dev->forward = NULL; +@@ -85,10 +86,9 @@ void ax25_dev_device_up(struct net_device *dev) + #endif + + spin_lock_bh(&ax25_dev_lock); +- ax25_dev->next = ax25_dev_list; +- ax25_dev_list = ax25_dev; ++ list_add(&ax25_dev->list, &ax25_dev_list); ++ dev->ax25_ptr = ax25_dev; + spin_unlock_bh(&ax25_dev_lock); +- ax25_dev_hold(ax25_dev); + + ax25_register_dev_sysctl(ax25_dev); + } +@@ -111,32 +111,19 @@ void ax25_dev_device_down(struct net_device *dev) + /* + * Remove any packet forwarding that points to this device. + */ +- for (s = ax25_dev_list; s != NULL; s = s->next) ++ list_for_each_entry(s, &ax25_dev_list, list) + if (s->forward == dev) + s->forward = NULL; + +- if ((s = ax25_dev_list) == ax25_dev) { +- ax25_dev_list = s->next; +- goto unlock_put; +- } +- +- while (s != NULL && s->next != NULL) { +- if (s->next == ax25_dev) { +- s->next = ax25_dev->next; +- goto unlock_put; ++ list_for_each_entry(s, &ax25_dev_list, list) { ++ if (s == ax25_dev) { ++ list_del(&s->list); ++ break; + } +- +- s = s->next; + } +- spin_unlock_bh(&ax25_dev_lock); +- dev->ax25_ptr = NULL; +- ax25_dev_put(ax25_dev); +- return; + +-unlock_put: +- spin_unlock_bh(&ax25_dev_lock); +- ax25_dev_put(ax25_dev); + dev->ax25_ptr = NULL; ++ spin_unlock_bh(&ax25_dev_lock); + netdev_put(dev, &ax25_dev->dev_tracker); + ax25_dev_put(ax25_dev); + } +@@ -200,16 +187,13 @@ struct net_device *ax25_fwd_dev(struct net_device *dev) + */ + void __exit ax25_dev_free(void) + { +- ax25_dev *s, *ax25_dev; ++ ax25_dev *s, *n; + + spin_lock_bh(&ax25_dev_lock); +- ax25_dev = ax25_dev_list; +- while (ax25_dev != NULL) { +- s = ax25_dev; +- netdev_put(ax25_dev->dev, &ax25_dev->dev_tracker); +- ax25_dev = ax25_dev->next; ++ list_for_each_entry_safe(s, n, &ax25_dev_list, list) { ++ netdev_put(s->dev, &s->dev_tracker); ++ list_del(&s->list); + kfree(s); + } +- ax25_dev_list = NULL; + spin_unlock_bh(&ax25_dev_lock); + } +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 6ab404dda7949..08ae30fd31551 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -1173,8 +1173,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type) + + list_for_each_entry(d, &hci_dev_list, list) { + if (!test_bit(HCI_UP, &d->flags) || +- hci_dev_test_flag(d, HCI_USER_CHANNEL) || +- d->dev_type != HCI_PRIMARY) ++ hci_dev_test_flag(d, HCI_USER_CHANNEL)) + continue; + + /* Simple routing: +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index bc5086423ab83..24f6b6a5c7721 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -395,11 +395,6 @@ int hci_inquiry(void __user *arg) + goto done; + } + +- if (hdev->dev_type != HCI_PRIMARY) { +- err = -EOPNOTSUPP; +- goto done; +- } +- + if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { + err = -EOPNOTSUPP; + goto done; +@@ -752,11 +747,6 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) + goto done; + } + +- if (hdev->dev_type != HCI_PRIMARY) { +- err = -EOPNOTSUPP; +- goto done; +- } +- + if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { + err = -EOPNOTSUPP; + goto done; +@@ -910,7 +900,7 @@ int hci_get_dev_info(void __user *arg) + + strscpy(di.name, hdev->name, sizeof(di.name)); + di.bdaddr = hdev->bdaddr; +- di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4); ++ di.type = (hdev->bus & 0x0f); + di.flags = flags; + di.pkt_type = hdev->pkt_type; + if (lmp_bredr_capable(hdev)) { +@@ -1026,8 +1016,7 @@ static void hci_power_on(struct work_struct *work) + */ + if (hci_dev_test_flag(hdev, HCI_RFKILLED) || + hci_dev_test_flag(hdev, HCI_UNCONFIGURED) || +- (hdev->dev_type == HCI_PRIMARY && +- !bacmp(&hdev->bdaddr, BDADDR_ANY) && ++ (!bacmp(&hdev->bdaddr, BDADDR_ANY) && + !bacmp(&hdev->static_addr, BDADDR_ANY))) { + hci_dev_clear_flag(hdev, HCI_AUTO_OFF); + hci_dev_do_close(hdev); +@@ -1769,6 +1758,15 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance, + + adv->pending = true; + adv->instance = instance; ++ ++ /* If controller support only one set and the instance is set to ++ * 1 then there is no option other than using handle 0x00. ++ */ ++ if (hdev->le_num_of_adv_sets == 1 && instance == 1) ++ adv->handle = 0x00; ++ else ++ adv->handle = instance; ++ + list_add(&adv->list, &hdev->adv_instances); + hdev->adv_instance_cnt++; + } +@@ -2635,21 +2633,7 @@ int hci_register_dev(struct hci_dev *hdev) + if (!hdev->open || !hdev->close || !hdev->send) + return -EINVAL; + +- /* Do not allow HCI_AMP devices to register at index 0, +- * so the index can be used as the AMP controller ID. +- */ +- switch (hdev->dev_type) { +- case HCI_PRIMARY: +- id = ida_alloc_max(&hci_index_ida, HCI_MAX_ID - 1, GFP_KERNEL); +- break; +- case HCI_AMP: +- id = ida_alloc_range(&hci_index_ida, 1, HCI_MAX_ID - 1, +- GFP_KERNEL); +- break; +- default: +- return -EINVAL; +- } +- ++ id = ida_alloc_max(&hci_index_ida, HCI_MAX_ID - 1, GFP_KERNEL); + if (id < 0) + return id; + +@@ -2701,12 +2685,10 @@ int hci_register_dev(struct hci_dev *hdev) + hci_dev_set_flag(hdev, HCI_SETUP); + hci_dev_set_flag(hdev, HCI_AUTO_OFF); + +- if (hdev->dev_type == HCI_PRIMARY) { +- /* Assume BR/EDR support until proven otherwise (such as +- * through reading supported features during init. +- */ +- hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); +- } ++ /* Assume BR/EDR support until proven otherwise (such as ++ * through reading supported features during init. ++ */ ++ hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); + + write_lock(&hci_dev_list_lock); + list_add(&hdev->list, &hci_dev_list); +@@ -3242,17 +3224,7 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, + + hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT; + +- switch (hdev->dev_type) { +- case HCI_PRIMARY: +- hci_add_acl_hdr(skb, conn->handle, flags); +- break; +- case HCI_AMP: +- hci_add_acl_hdr(skb, chan->handle, flags); +- break; +- default: +- bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type); +- return; +- } ++ hci_add_acl_hdr(skb, conn->handle, flags); + + list = skb_shinfo(skb)->frag_list; + if (!list) { +@@ -3412,9 +3384,6 @@ static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote) + case ACL_LINK: + cnt = hdev->acl_cnt; + break; +- case AMP_LINK: +- cnt = hdev->block_cnt; +- break; + case SCO_LINK: + case ESCO_LINK: + cnt = hdev->sco_cnt; +@@ -3612,12 +3581,6 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) + + } + +-static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb) +-{ +- /* Calculate count of blocks used by this packet */ +- return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len); +-} +- + static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type) + { + unsigned long last_tx; +@@ -3731,81 +3694,15 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev) + hci_prio_recalculate(hdev, ACL_LINK); + } + +-static void hci_sched_acl_blk(struct hci_dev *hdev) +-{ +- unsigned int cnt = hdev->block_cnt; +- struct hci_chan *chan; +- struct sk_buff *skb; +- int quote; +- u8 type; +- +- BT_DBG("%s", hdev->name); +- +- if (hdev->dev_type == HCI_AMP) +- type = AMP_LINK; +- else +- type = ACL_LINK; +- +- __check_timeout(hdev, cnt, type); +- +- while (hdev->block_cnt > 0 && +- (chan = hci_chan_sent(hdev, type, "e))) { +- u32 priority = (skb_peek(&chan->data_q))->priority; +- while (quote > 0 && (skb = skb_peek(&chan->data_q))) { +- int blocks; +- +- BT_DBG("chan %p skb %p len %d priority %u", chan, skb, +- skb->len, skb->priority); +- +- /* Stop if priority has changed */ +- if (skb->priority < priority) +- break; +- +- skb = skb_dequeue(&chan->data_q); +- +- blocks = __get_blocks(hdev, skb); +- if (blocks > hdev->block_cnt) +- return; +- +- hci_conn_enter_active_mode(chan->conn, +- bt_cb(skb)->force_active); +- +- hci_send_frame(hdev, skb); +- hdev->acl_last_tx = jiffies; +- +- hdev->block_cnt -= blocks; +- quote -= blocks; +- +- chan->sent += blocks; +- chan->conn->sent += blocks; +- } +- } +- +- if (cnt != hdev->block_cnt) +- hci_prio_recalculate(hdev, type); +-} +- + static void hci_sched_acl(struct hci_dev *hdev) + { + BT_DBG("%s", hdev->name); + + /* No ACL link over BR/EDR controller */ +- if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_PRIMARY) +- return; +- +- /* No AMP link over AMP controller */ +- if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP) ++ if (!hci_conn_num(hdev, ACL_LINK)) + return; + +- switch (hdev->flow_ctl_mode) { +- case HCI_FLOW_CTL_MODE_PACKET_BASED: +- hci_sched_acl_pkt(hdev); +- break; +- +- case HCI_FLOW_CTL_MODE_BLOCK_BASED: +- hci_sched_acl_blk(hdev); +- break; +- } ++ hci_sched_acl_pkt(hdev); + } + + static void hci_sched_le(struct hci_dev *hdev) +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 4de8f0dc1a523..cce73749f2dce 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -913,21 +913,6 @@ static u8 hci_cc_read_local_ext_features(struct hci_dev *hdev, void *data, + return rp->status; + } + +-static u8 hci_cc_read_flow_control_mode(struct hci_dev *hdev, void *data, +- struct sk_buff *skb) +-{ +- struct hci_rp_read_flow_control_mode *rp = data; +- +- bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); +- +- if (rp->status) +- return rp->status; +- +- hdev->flow_ctl_mode = rp->mode; +- +- return rp->status; +-} +- + static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { +@@ -1071,28 +1056,6 @@ static u8 hci_cc_write_page_scan_type(struct hci_dev *hdev, void *data, + return rp->status; + } + +-static u8 hci_cc_read_data_block_size(struct hci_dev *hdev, void *data, +- struct sk_buff *skb) +-{ +- struct hci_rp_read_data_block_size *rp = data; +- +- bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); +- +- if (rp->status) +- return rp->status; +- +- hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); +- hdev->block_len = __le16_to_cpu(rp->block_len); +- hdev->num_blocks = __le16_to_cpu(rp->num_blocks); +- +- hdev->block_cnt = hdev->num_blocks; +- +- BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, +- hdev->block_cnt, hdev->block_len); +- +- return rp->status; +-} +- + static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { +@@ -1127,30 +1090,6 @@ static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data, + return rp->status; + } + +-static u8 hci_cc_read_local_amp_info(struct hci_dev *hdev, void *data, +- struct sk_buff *skb) +-{ +- struct hci_rp_read_local_amp_info *rp = data; +- +- bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); +- +- if (rp->status) +- return rp->status; +- +- hdev->amp_status = rp->amp_status; +- hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); +- hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); +- hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); +- hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); +- hdev->amp_type = rp->amp_type; +- hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); +- hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); +- hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); +- hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); +- +- return rp->status; +-} +- + static u8 hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { +@@ -4121,12 +4060,6 @@ static const struct hci_cc { + HCI_CC(HCI_OP_READ_PAGE_SCAN_TYPE, hci_cc_read_page_scan_type, + sizeof(struct hci_rp_read_page_scan_type)), + HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_TYPE, hci_cc_write_page_scan_type), +- HCI_CC(HCI_OP_READ_DATA_BLOCK_SIZE, hci_cc_read_data_block_size, +- sizeof(struct hci_rp_read_data_block_size)), +- HCI_CC(HCI_OP_READ_FLOW_CONTROL_MODE, hci_cc_read_flow_control_mode, +- sizeof(struct hci_rp_read_flow_control_mode)), +- HCI_CC(HCI_OP_READ_LOCAL_AMP_INFO, hci_cc_read_local_amp_info, +- sizeof(struct hci_rp_read_local_amp_info)), + HCI_CC(HCI_OP_READ_CLOCK, hci_cc_read_clock, + sizeof(struct hci_rp_read_clock)), + HCI_CC(HCI_OP_READ_ENC_KEY_SIZE, hci_cc_read_enc_key_size, +@@ -4317,7 +4250,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status) + hci_dev_lock(hdev); + + /* Remove connection if command failed */ +- for (i = 0; cp->num_cis; cp->num_cis--, i++) { ++ for (i = 0; i < cp->num_cis; i++) { + struct hci_conn *conn; + u16 handle; + +@@ -4333,6 +4266,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status) + hci_conn_del(conn); + } + } ++ cp->num_cis = 0; + + if (pending) + hci_le_create_cis_pending(hdev); +@@ -4461,11 +4395,6 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + flex_array_size(ev, handles, ev->num))) + return; + +- if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { +- bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); +- return; +- } +- + bt_dev_dbg(hdev, "num %d", ev->num); + + for (i = 0; i < ev->num; i++) { +@@ -4533,78 +4462,6 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + queue_work(hdev->workqueue, &hdev->tx_work); + } + +-static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, +- __u16 handle) +-{ +- struct hci_chan *chan; +- +- switch (hdev->dev_type) { +- case HCI_PRIMARY: +- return hci_conn_hash_lookup_handle(hdev, handle); +- case HCI_AMP: +- chan = hci_chan_lookup_handle(hdev, handle); +- if (chan) +- return chan->conn; +- break; +- default: +- bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type); +- break; +- } +- +- return NULL; +-} +- +-static void hci_num_comp_blocks_evt(struct hci_dev *hdev, void *data, +- struct sk_buff *skb) +-{ +- struct hci_ev_num_comp_blocks *ev = data; +- int i; +- +- if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS, +- flex_array_size(ev, handles, ev->num_hndl))) +- return; +- +- if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { +- bt_dev_err(hdev, "wrong event for mode %d", +- hdev->flow_ctl_mode); +- return; +- } +- +- bt_dev_dbg(hdev, "num_blocks %d num_hndl %d", ev->num_blocks, +- ev->num_hndl); +- +- for (i = 0; i < ev->num_hndl; i++) { +- struct hci_comp_blocks_info *info = &ev->handles[i]; +- struct hci_conn *conn = NULL; +- __u16 handle, block_count; +- +- handle = __le16_to_cpu(info->handle); +- block_count = __le16_to_cpu(info->blocks); +- +- conn = __hci_conn_lookup_handle(hdev, handle); +- if (!conn) +- continue; +- +- conn->sent -= block_count; +- +- switch (conn->type) { +- case ACL_LINK: +- case AMP_LINK: +- hdev->block_cnt += block_count; +- if (hdev->block_cnt > hdev->num_blocks) +- hdev->block_cnt = hdev->num_blocks; +- break; +- +- default: +- bt_dev_err(hdev, "unknown type %d conn %p", +- conn->type, conn); +- break; +- } +- } +- +- queue_work(hdev->workqueue, &hdev->tx_work); +-} +- + static void hci_mode_change_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { +@@ -7512,9 +7369,6 @@ static const struct hci_ev { + /* [0x3e = HCI_EV_LE_META] */ + HCI_EV_REQ_VL(HCI_EV_LE_META, hci_le_meta_evt, + sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE), +- /* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */ +- HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt, +- sizeof(struct hci_ev_num_comp_blocks)), + /* [0xff = HCI_EV_VENDOR] */ + HCI_EV_VL(HCI_EV_VENDOR, msft_vendor_evt, 0, HCI_MAX_EVENT_SIZE), + }; +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index 703b84bd48d5b..69c2ba1e843eb 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -485,7 +485,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) + return NULL; + + ni = skb_put(skb, HCI_MON_NEW_INDEX_SIZE); +- ni->type = hdev->dev_type; ++ ni->type = 0x00; /* Old hdev->dev_type */ + ni->bus = hdev->bus; + bacpy(&ni->bdaddr, &hdev->bdaddr); + memcpy_and_pad(ni->name, sizeof(ni->name), hdev->name, +@@ -1007,9 +1007,6 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, + if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) + return -EOPNOTSUPP; + +- if (hdev->dev_type != HCI_PRIMARY) +- return -EOPNOTSUPP; +- + switch (cmd) { + case HCISETRAW: + if (!capable(CAP_NET_ADMIN)) +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 4c707eb64e6f6..64f794d198cdc 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -1043,11 +1043,10 @@ static int hci_disable_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) + struct hci_cp_ext_adv_set *set; + u8 data[sizeof(*cp) + sizeof(*set) * 1]; + u8 size; ++ struct adv_info *adv = NULL; + + /* If request specifies an instance that doesn't exist, fail */ + if (instance > 0) { +- struct adv_info *adv; +- + adv = hci_find_adv_instance(hdev, instance); + if (!adv) + return -EINVAL; +@@ -1066,7 +1065,7 @@ static int hci_disable_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) + cp->num_of_sets = !!instance; + cp->enable = 0x00; + +- set->handle = instance; ++ set->handle = adv ? adv->handle : instance; + + size = sizeof(*cp) + sizeof(*set) * cp->num_of_sets; + +@@ -1235,31 +1234,27 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) + + static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance) + { +- struct { +- struct hci_cp_le_set_ext_scan_rsp_data cp; +- u8 data[HCI_MAX_EXT_AD_LENGTH]; +- } pdu; ++ DEFINE_FLEX(struct hci_cp_le_set_ext_scan_rsp_data, pdu, data, length, ++ HCI_MAX_EXT_AD_LENGTH); + u8 len; + struct adv_info *adv = NULL; + int err; + +- memset(&pdu, 0, sizeof(pdu)); +- + if (instance) { + adv = hci_find_adv_instance(hdev, instance); + if (!adv || !adv->scan_rsp_changed) + return 0; + } + +- len = eir_create_scan_rsp(hdev, instance, pdu.data); ++ len = eir_create_scan_rsp(hdev, instance, pdu->data); + +- pdu.cp.handle = instance; +- pdu.cp.length = len; +- pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; +- pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; ++ pdu->handle = adv ? adv->handle : instance; ++ pdu->length = len; ++ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE; ++ pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG; + + err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, +- sizeof(pdu.cp) + len, &pdu.cp, ++ struct_size(pdu, data, len), pdu, + HCI_CMD_TIMEOUT); + if (err) + return err; +@@ -1267,7 +1262,7 @@ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance) + if (adv) { + adv->scan_rsp_changed = false; + } else { +- memcpy(hdev->scan_rsp_data, pdu.data, len); ++ memcpy(hdev->scan_rsp_data, pdu->data, len); + hdev->scan_rsp_data_len = len; + } + +@@ -1335,7 +1330,7 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance) + + memset(set, 0, sizeof(*set)); + +- set->handle = instance; ++ set->handle = adv ? adv->handle : instance; + + /* Set duration per instance since controller is responsible for + * scheduling it. +@@ -1411,29 +1406,25 @@ static int hci_set_per_adv_params_sync(struct hci_dev *hdev, u8 instance, + + static int hci_set_per_adv_data_sync(struct hci_dev *hdev, u8 instance) + { +- struct { +- struct hci_cp_le_set_per_adv_data cp; +- u8 data[HCI_MAX_PER_AD_LENGTH]; +- } pdu; ++ DEFINE_FLEX(struct hci_cp_le_set_per_adv_data, pdu, data, length, ++ HCI_MAX_PER_AD_LENGTH); + u8 len; +- +- memset(&pdu, 0, sizeof(pdu)); ++ struct adv_info *adv = NULL; + + if (instance) { +- struct adv_info *adv = hci_find_adv_instance(hdev, instance); +- ++ adv = hci_find_adv_instance(hdev, instance); + if (!adv || !adv->periodic) + return 0; + } + +- len = eir_create_per_adv_data(hdev, instance, pdu.data); ++ len = eir_create_per_adv_data(hdev, instance, pdu->data); + +- pdu.cp.length = len; +- pdu.cp.handle = instance; +- pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; ++ pdu->length = len; ++ pdu->handle = adv ? adv->handle : instance; ++ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE; + + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_PER_ADV_DATA, +- sizeof(pdu.cp) + len, &pdu, ++ struct_size(pdu, data, len), pdu, + HCI_CMD_TIMEOUT); + } + +@@ -1727,31 +1718,27 @@ int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason) + + static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance) + { +- struct { +- struct hci_cp_le_set_ext_adv_data cp; +- u8 data[HCI_MAX_EXT_AD_LENGTH]; +- } pdu; ++ DEFINE_FLEX(struct hci_cp_le_set_ext_adv_data, pdu, data, length, ++ HCI_MAX_EXT_AD_LENGTH); + u8 len; + struct adv_info *adv = NULL; + int err; + +- memset(&pdu, 0, sizeof(pdu)); +- + if (instance) { + adv = hci_find_adv_instance(hdev, instance); + if (!adv || !adv->adv_data_changed) + return 0; + } + +- len = eir_create_adv_data(hdev, instance, pdu.data); ++ len = eir_create_adv_data(hdev, instance, pdu->data); + +- pdu.cp.length = len; +- pdu.cp.handle = instance; +- pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; +- pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; ++ pdu->length = len; ++ pdu->handle = adv ? adv->handle : instance; ++ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE; ++ pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG; + + err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_DATA, +- sizeof(pdu.cp) + len, &pdu.cp, ++ struct_size(pdu, data, len), pdu, + HCI_CMD_TIMEOUT); + if (err) + return err; +@@ -1760,7 +1747,7 @@ static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance) + if (adv) { + adv->adv_data_changed = false; + } else { +- memcpy(hdev->adv_data, pdu.data, len); ++ memcpy(hdev->adv_data, pdu->data, len); + hdev->adv_data_len = len; + } + +@@ -3523,10 +3510,6 @@ static int hci_unconf_init_sync(struct hci_dev *hdev) + /* Read Local Supported Features. */ + static int hci_read_local_features_sync(struct hci_dev *hdev) + { +- /* Not all AMP controllers support this command */ +- if (hdev->dev_type == HCI_AMP && !(hdev->commands[14] & 0x20)) +- return 0; +- + return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_FEATURES, + 0, NULL, HCI_CMD_TIMEOUT); + } +@@ -3561,51 +3544,6 @@ static int hci_read_local_cmds_sync(struct hci_dev *hdev) + return 0; + } + +-/* Read Local AMP Info */ +-static int hci_read_local_amp_info_sync(struct hci_dev *hdev) +-{ +- return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_AMP_INFO, +- 0, NULL, HCI_CMD_TIMEOUT); +-} +- +-/* Read Data Blk size */ +-static int hci_read_data_block_size_sync(struct hci_dev *hdev) +-{ +- return __hci_cmd_sync_status(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, +- 0, NULL, HCI_CMD_TIMEOUT); +-} +- +-/* Read Flow Control Mode */ +-static int hci_read_flow_control_mode_sync(struct hci_dev *hdev) +-{ +- return __hci_cmd_sync_status(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, +- 0, NULL, HCI_CMD_TIMEOUT); +-} +- +-/* Read Location Data */ +-static int hci_read_location_data_sync(struct hci_dev *hdev) +-{ +- return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCATION_DATA, +- 0, NULL, HCI_CMD_TIMEOUT); +-} +- +-/* AMP Controller init stage 1 command sequence */ +-static const struct hci_init_stage amp_init1[] = { +- /* HCI_OP_READ_LOCAL_VERSION */ +- HCI_INIT(hci_read_local_version_sync), +- /* HCI_OP_READ_LOCAL_COMMANDS */ +- HCI_INIT(hci_read_local_cmds_sync), +- /* HCI_OP_READ_LOCAL_AMP_INFO */ +- HCI_INIT(hci_read_local_amp_info_sync), +- /* HCI_OP_READ_DATA_BLOCK_SIZE */ +- HCI_INIT(hci_read_data_block_size_sync), +- /* HCI_OP_READ_FLOW_CONTROL_MODE */ +- HCI_INIT(hci_read_flow_control_mode_sync), +- /* HCI_OP_READ_LOCATION_DATA */ +- HCI_INIT(hci_read_location_data_sync), +- {} +-}; +- + static int hci_init1_sync(struct hci_dev *hdev) + { + int err; +@@ -3619,28 +3557,9 @@ static int hci_init1_sync(struct hci_dev *hdev) + return err; + } + +- switch (hdev->dev_type) { +- case HCI_PRIMARY: +- hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; +- return hci_init_stage_sync(hdev, br_init1); +- case HCI_AMP: +- hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; +- return hci_init_stage_sync(hdev, amp_init1); +- default: +- bt_dev_err(hdev, "Unknown device type %d", hdev->dev_type); +- break; +- } +- +- return 0; ++ return hci_init_stage_sync(hdev, br_init1); + } + +-/* AMP Controller init stage 2 command sequence */ +-static const struct hci_init_stage amp_init2[] = { +- /* HCI_OP_READ_LOCAL_FEATURES */ +- HCI_INIT(hci_read_local_features_sync), +- {} +-}; +- + /* Read Buffer Size (ACL mtu, max pkt, etc.) */ + static int hci_read_buffer_size_sync(struct hci_dev *hdev) + { +@@ -3898,9 +3817,6 @@ static int hci_init2_sync(struct hci_dev *hdev) + + bt_dev_dbg(hdev, ""); + +- if (hdev->dev_type == HCI_AMP) +- return hci_init_stage_sync(hdev, amp_init2); +- + err = hci_init_stage_sync(hdev, hci_init2); + if (err) + return err; +@@ -4728,13 +4644,6 @@ static int hci_init_sync(struct hci_dev *hdev) + if (err < 0) + return err; + +- /* HCI_PRIMARY covers both single-mode LE, BR/EDR and dual-mode +- * BR/EDR/LE type controllers. AMP controllers only need the +- * first two stages of init. +- */ +- if (hdev->dev_type != HCI_PRIMARY) +- return 0; +- + err = hci_init3_sync(hdev); + if (err < 0) + return err; +@@ -4963,12 +4872,8 @@ int hci_dev_open_sync(struct hci_dev *hdev) + * In case of user channel usage, it is not important + * if a public address or static random address is + * available. +- * +- * This check is only valid for BR/EDR controllers +- * since AMP controllers do not have an address. + */ + if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && +- hdev->dev_type == HCI_PRIMARY && + !bacmp(&hdev->bdaddr, BDADDR_ANY) && + !bacmp(&hdev->static_addr, BDADDR_ANY)) { + ret = -EADDRNOTAVAIL; +@@ -5003,8 +4908,7 @@ int hci_dev_open_sync(struct hci_dev *hdev) + !hci_dev_test_flag(hdev, HCI_CONFIG) && + !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && + !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && +- hci_dev_test_flag(hdev, HCI_MGMT) && +- hdev->dev_type == HCI_PRIMARY) { ++ hci_dev_test_flag(hdev, HCI_MGMT)) { + ret = hci_powered_update_sync(hdev); + mgmt_power_on(hdev, ret); + } +@@ -5149,8 +5053,7 @@ int hci_dev_close_sync(struct hci_dev *hdev) + + auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF); + +- if (!auto_off && hdev->dev_type == HCI_PRIMARY && +- !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && ++ if (!auto_off && !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + hci_dev_test_flag(hdev, HCI_MGMT)) + __mgmt_power_off(hdev); + +@@ -5212,9 +5115,6 @@ int hci_dev_close_sync(struct hci_dev *hdev) + hdev->flags &= BIT(HCI_RAW); + hci_dev_clear_volatile_flags(hdev); + +- /* Controller radio is available but is currently powered down */ +- hdev->amp_status = AMP_STATUS_POWERED_DOWN; +- + memset(hdev->eir, 0, sizeof(hdev->eir)); + memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); + bacpy(&hdev->random_addr, BDADDR_ANY); +@@ -5251,8 +5151,7 @@ static int hci_power_on_sync(struct hci_dev *hdev) + */ + if (hci_dev_test_flag(hdev, HCI_RFKILLED) || + hci_dev_test_flag(hdev, HCI_UNCONFIGURED) || +- (hdev->dev_type == HCI_PRIMARY && +- !bacmp(&hdev->bdaddr, BDADDR_ANY) && ++ (!bacmp(&hdev->bdaddr, BDADDR_ANY) && + !bacmp(&hdev->static_addr, BDADDR_ANY))) { + hci_dev_clear_flag(hdev, HCI_AUTO_OFF); + hci_dev_close_sync(hdev); +@@ -5354,27 +5253,11 @@ int hci_stop_discovery_sync(struct hci_dev *hdev) + return 0; + } + +-static int hci_disconnect_phy_link_sync(struct hci_dev *hdev, u16 handle, +- u8 reason) +-{ +- struct hci_cp_disconn_phy_link cp; +- +- memset(&cp, 0, sizeof(cp)); +- cp.phy_handle = HCI_PHY_HANDLE(handle); +- cp.reason = reason; +- +- return __hci_cmd_sync_status(hdev, HCI_OP_DISCONN_PHY_LINK, +- sizeof(cp), &cp, HCI_CMD_TIMEOUT); +-} +- + static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn, + u8 reason) + { + struct hci_cp_disconnect cp; + +- if (conn->type == AMP_LINK) +- return hci_disconnect_phy_link_sync(hdev, conn->handle, reason); +- + if (test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) { + /* This is a BIS connection, hci_conn_del will + * do the necessary cleanup. +@@ -6493,10 +6376,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) + + int hci_le_create_cis_sync(struct hci_dev *hdev) + { +- struct { +- struct hci_cp_le_create_cis cp; +- struct hci_cis cis[0x1f]; +- } cmd; ++ DEFINE_FLEX(struct hci_cp_le_create_cis, cmd, cis, num_cis, 0x1f); ++ size_t aux_num_cis = 0; + struct hci_conn *conn; + u8 cig = BT_ISO_QOS_CIG_UNSET; + +@@ -6523,8 +6404,6 @@ int hci_le_create_cis_sync(struct hci_dev *hdev) + * remains pending. + */ + +- memset(&cmd, 0, sizeof(cmd)); +- + hci_dev_lock(hdev); + + rcu_read_lock(); +@@ -6561,7 +6440,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev) + goto done; + + list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) { +- struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis]; ++ struct hci_cis *cis = &cmd->cis[aux_num_cis]; + + if (hci_conn_check_create_cis(conn) || + conn->iso_qos.ucast.cig != cig) +@@ -6570,25 +6449,25 @@ int hci_le_create_cis_sync(struct hci_dev *hdev) + set_bit(HCI_CONN_CREATE_CIS, &conn->flags); + cis->acl_handle = cpu_to_le16(conn->parent->handle); + cis->cis_handle = cpu_to_le16(conn->handle); +- cmd.cp.num_cis++; ++ aux_num_cis++; + +- if (cmd.cp.num_cis >= ARRAY_SIZE(cmd.cis)) ++ if (aux_num_cis >= 0x1f) + break; + } ++ cmd->num_cis = aux_num_cis; + + done: + rcu_read_unlock(); + + hci_dev_unlock(hdev); + +- if (!cmd.cp.num_cis) ++ if (!aux_num_cis) + return 0; + + /* Wait for HCI_LE_CIS_Established */ + return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_CREATE_CIS, +- sizeof(cmd.cp) + sizeof(cmd.cis[0]) * +- cmd.cp.num_cis, &cmd, +- HCI_EVT_LE_CIS_ESTABLISHED, ++ struct_size(cmd, cis, cmd->num_cis), ++ cmd, HCI_EVT_LE_CIS_ESTABLISHED, + conn->conn_timeout, NULL); + } + +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 6bed4aa8291de..6cb41f9d174e2 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -85,8 +85,9 @@ static void iso_sock_disconn(struct sock *sk); + + typedef bool (*iso_sock_match_t)(struct sock *sk, void *data); + +-static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst, +- iso_sock_match_t match, void *data); ++static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst, ++ enum bt_sock_state state, ++ iso_sock_match_t match, void *data); + + /* ---- ISO timers ---- */ + #define ISO_CONN_TIMEOUT (HZ * 40) +@@ -233,10 +234,11 @@ static void iso_conn_del(struct hci_conn *hcon, int err) + * terminated are not processed anymore. + */ + if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) { +- parent = iso_get_sock_listen(&hcon->src, +- &hcon->dst, +- iso_match_conn_sync_handle, +- hcon); ++ parent = iso_get_sock(&hcon->src, ++ &hcon->dst, ++ BT_LISTEN, ++ iso_match_conn_sync_handle, ++ hcon); + + if (parent) { + set_bit(BT_SK_PA_SYNC_TERM, +@@ -581,22 +583,23 @@ static struct sock *__iso_get_sock_listen_by_sid(bdaddr_t *ba, bdaddr_t *bc, + return NULL; + } + +-/* Find socket listening: ++/* Find socket in given state: + * source bdaddr (Unicast) + * destination bdaddr (Broadcast only) + * match func - pass NULL to ignore + * match func data - pass -1 to ignore + * Returns closest match. + */ +-static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst, +- iso_sock_match_t match, void *data) ++static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst, ++ enum bt_sock_state state, ++ iso_sock_match_t match, void *data) + { + struct sock *sk = NULL, *sk1 = NULL; + + read_lock(&iso_sk_list.lock); + + sk_for_each(sk, &iso_sk_list.head) { +- if (sk->sk_state != BT_LISTEN) ++ if (sk->sk_state != state) + continue; + + /* Match Broadcast destination */ +@@ -1777,32 +1780,37 @@ static void iso_conn_ready(struct iso_conn *conn) + HCI_EVT_LE_BIG_SYNC_ESTABILISHED); + + /* Get reference to PA sync parent socket, if it exists */ +- parent = iso_get_sock_listen(&hcon->src, +- &hcon->dst, +- iso_match_pa_sync_flag, NULL); ++ parent = iso_get_sock(&hcon->src, &hcon->dst, ++ BT_LISTEN, ++ iso_match_pa_sync_flag, ++ NULL); + if (!parent && ev) +- parent = iso_get_sock_listen(&hcon->src, +- &hcon->dst, +- iso_match_big, ev); ++ parent = iso_get_sock(&hcon->src, ++ &hcon->dst, ++ BT_LISTEN, ++ iso_match_big, ev); + } else if (test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) { + ev2 = hci_recv_event_data(hcon->hdev, + HCI_EV_LE_PA_SYNC_ESTABLISHED); + if (ev2) +- parent = iso_get_sock_listen(&hcon->src, +- &hcon->dst, +- iso_match_sid, ev2); ++ parent = iso_get_sock(&hcon->src, ++ &hcon->dst, ++ BT_LISTEN, ++ iso_match_sid, ev2); + } else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) { + ev3 = hci_recv_event_data(hcon->hdev, + HCI_EVT_LE_BIG_INFO_ADV_REPORT); + if (ev3) +- parent = iso_get_sock_listen(&hcon->src, +- &hcon->dst, +- iso_match_sync_handle, ev3); ++ parent = iso_get_sock(&hcon->src, ++ &hcon->dst, ++ BT_LISTEN, ++ iso_match_sync_handle, ++ ev3); + } + + if (!parent) +- parent = iso_get_sock_listen(&hcon->src, +- BDADDR_ANY, NULL, NULL); ++ parent = iso_get_sock(&hcon->src, BDADDR_ANY, ++ BT_LISTEN, NULL, NULL); + + if (!parent) + return; +@@ -1923,8 +1931,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + */ + ev1 = hci_recv_event_data(hdev, HCI_EV_LE_PA_SYNC_ESTABLISHED); + if (ev1) { +- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, iso_match_sid, +- ev1); ++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN, ++ iso_match_sid, ev1); + if (sk && !ev1->status) + iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle); + +@@ -1934,12 +1942,12 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT); + if (ev2) { + /* Try to get PA sync listening socket, if it exists */ +- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, +- iso_match_pa_sync_flag, NULL); ++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN, ++ iso_match_pa_sync_flag, NULL); + + if (!sk) { +- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, +- iso_match_sync_handle, ev2); ++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN, ++ iso_match_sync_handle, ev2); + + /* If PA Sync is in process of terminating, + * do not handle any more BIGInfo adv reports. +@@ -1979,8 +1987,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + u8 *base; + struct hci_conn *hcon; + +- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, +- iso_match_sync_handle_pa_report, ev3); ++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN, ++ iso_match_sync_handle_pa_report, ev3); + if (!sk) + goto done; + +@@ -2029,7 +2037,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + hcon->le_per_adv_data_len = 0; + } + } else { +- sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL); ++ sk = iso_get_sock(&hdev->bdaddr, BDADDR_ANY, ++ BT_LISTEN, NULL, NULL); + } + + done: +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 3f7a82f10fe98..4a633c1b68825 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -457,6 +457,9 @@ struct l2cap_chan *l2cap_chan_create(void) + /* Set default lock nesting level */ + atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL); + ++ /* Available receive buffer space is initially unknown */ ++ chan->rx_avail = -1; ++ + write_lock(&chan_list_lock); + list_add(&chan->global_l, &chan_list); + write_unlock(&chan_list_lock); +@@ -538,6 +541,28 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) + } + EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); + ++static __u16 l2cap_le_rx_credits(struct l2cap_chan *chan) ++{ ++ size_t sdu_len = chan->sdu ? chan->sdu->len : 0; ++ ++ if (chan->mps == 0) ++ return 0; ++ ++ /* If we don't know the available space in the receiver buffer, give ++ * enough credits for a full packet. ++ */ ++ if (chan->rx_avail == -1) ++ return (chan->imtu / chan->mps) + 1; ++ ++ /* If we know how much space is available in the receive buffer, give ++ * out as many credits as would fill the buffer. ++ */ ++ if (chan->rx_avail <= sdu_len) ++ return 0; ++ ++ return DIV_ROUND_UP(chan->rx_avail - sdu_len, chan->mps); ++} ++ + static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits) + { + chan->sdu = NULL; +@@ -546,8 +571,7 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits) + chan->tx_credits = tx_credits; + /* Derive MPS from connection MTU to stop HCI fragmentation */ + chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); +- /* Give enough credits for a full packet */ +- chan->rx_credits = (chan->imtu / chan->mps) + 1; ++ chan->rx_credits = l2cap_le_rx_credits(chan); + + skb_queue_head_init(&chan->tx_q); + } +@@ -559,7 +583,7 @@ static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits) + /* L2CAP implementations shall support a minimum MPS of 64 octets */ + if (chan->mps < L2CAP_ECRED_MIN_MPS) { + chan->mps = L2CAP_ECRED_MIN_MPS; +- chan->rx_credits = (chan->imtu / chan->mps) + 1; ++ chan->rx_credits = l2cap_le_rx_credits(chan); + } + } + +@@ -3906,7 +3930,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, + } + + static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, +- u8 *data, u8 rsp_code, u8 amp_id) ++ u8 *data, u8 rsp_code) + { + struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; + struct l2cap_conn_rsp rsp; +@@ -3985,17 +4009,8 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, + status = L2CAP_CS_AUTHOR_PEND; + chan->ops->defer(chan); + } else { +- /* Force pending result for AMP controllers. +- * The connection will succeed after the +- * physical link is up. +- */ +- if (amp_id == AMP_ID_BREDR) { +- l2cap_state_change(chan, BT_CONFIG); +- result = L2CAP_CR_SUCCESS; +- } else { +- l2cap_state_change(chan, BT_CONNECT2); +- result = L2CAP_CR_PEND; +- } ++ l2cap_state_change(chan, BT_CONNECT2); ++ result = L2CAP_CR_PEND; + status = L2CAP_CS_NO_INFO; + } + } else { +@@ -4060,7 +4075,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn, + mgmt_device_connected(hdev, hcon, NULL, 0); + hci_dev_unlock(hdev); + +- l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); ++ l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP); + return 0; + } + +@@ -6513,9 +6528,7 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) + { + struct l2cap_conn *conn = chan->conn; + struct l2cap_le_credits pkt; +- u16 return_credits; +- +- return_credits = (chan->imtu / chan->mps) + 1; ++ u16 return_credits = l2cap_le_rx_credits(chan); + + if (chan->rx_credits >= return_credits) + return; +@@ -6534,6 +6547,19 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) + l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); + } + ++void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail) ++{ ++ if (chan->rx_avail == rx_avail) ++ return; ++ ++ BT_DBG("chan %p has %zd bytes avail for rx", chan, rx_avail); ++ ++ chan->rx_avail = rx_avail; ++ ++ if (chan->state == BT_CONNECTED) ++ l2cap_chan_le_send_credits(chan); ++} ++ + static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb) + { + int err; +@@ -6543,6 +6569,12 @@ static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb) + /* Wait recv to confirm reception before updating the credits */ + err = chan->ops->recv(chan, skb); + ++ if (err < 0 && chan->rx_avail != -1) { ++ BT_ERR("Queueing received LE L2CAP data failed"); ++ l2cap_send_disconn_req(chan, ECONNRESET); ++ return err; ++ } ++ + /* Update credits whenever an SDU is received */ + l2cap_chan_le_send_credits(chan); + +@@ -6565,7 +6597,8 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) + } + + chan->rx_credits--; +- BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); ++ BT_DBG("chan %p: rx_credits %u -> %u", ++ chan, chan->rx_credits + 1, chan->rx_credits); + + /* Update if remote had run out of credits, this should only happens + * if the remote is not using the entire MPS. +@@ -7453,10 +7486,6 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) + struct l2cap_conn *conn = hcon->l2cap_data; + int len; + +- /* For AMP controller do not create l2cap conn */ +- if (!conn && hcon->hdev->dev_type != HCI_PRIMARY) +- goto drop; +- + if (!conn) + conn = l2cap_conn_add(hcon); + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 5cc83f906c123..8645461d45e81 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1131,6 +1131,34 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg, + return err; + } + ++static void l2cap_publish_rx_avail(struct l2cap_chan *chan) ++{ ++ struct sock *sk = chan->data; ++ ssize_t avail = sk->sk_rcvbuf - atomic_read(&sk->sk_rmem_alloc); ++ int expected_skbs, skb_overhead; ++ ++ if (avail <= 0) { ++ l2cap_chan_rx_avail(chan, 0); ++ return; ++ } ++ ++ if (!chan->mps) { ++ l2cap_chan_rx_avail(chan, -1); ++ return; ++ } ++ ++ /* Correct available memory by estimated sk_buff overhead. ++ * This is significant due to small transfer sizes. However, accept ++ * at least one full packet if receive space is non-zero. ++ */ ++ expected_skbs = DIV_ROUND_UP(avail, chan->mps); ++ skb_overhead = expected_skbs * sizeof(struct sk_buff); ++ if (skb_overhead < avail) ++ l2cap_chan_rx_avail(chan, avail - skb_overhead); ++ else ++ l2cap_chan_rx_avail(chan, -1); ++} ++ + static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags) + { +@@ -1167,28 +1195,33 @@ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg, + else + err = bt_sock_recvmsg(sock, msg, len, flags); + +- if (pi->chan->mode != L2CAP_MODE_ERTM) ++ if (pi->chan->mode != L2CAP_MODE_ERTM && ++ pi->chan->mode != L2CAP_MODE_LE_FLOWCTL && ++ pi->chan->mode != L2CAP_MODE_EXT_FLOWCTL) + return err; + +- /* Attempt to put pending rx data in the socket buffer */ +- + lock_sock(sk); + +- if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state)) +- goto done; ++ l2cap_publish_rx_avail(pi->chan); + +- if (pi->rx_busy_skb) { +- if (!__sock_queue_rcv_skb(sk, pi->rx_busy_skb)) +- pi->rx_busy_skb = NULL; +- else ++ /* Attempt to put pending rx data in the socket buffer */ ++ while (!list_empty(&pi->rx_busy)) { ++ struct l2cap_rx_busy *rx_busy = ++ list_first_entry(&pi->rx_busy, ++ struct l2cap_rx_busy, ++ list); ++ if (__sock_queue_rcv_skb(sk, rx_busy->skb) < 0) + goto done; ++ list_del(&rx_busy->list); ++ kfree(rx_busy); + } + + /* Restore data flow when half of the receive buffer is + * available. This avoids resending large numbers of + * frames. + */ +- if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1) ++ if (test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state) && ++ atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1) + l2cap_chan_busy(pi->chan, 0); + + done: +@@ -1449,17 +1482,20 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) + static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) + { + struct sock *sk = chan->data; ++ struct l2cap_pinfo *pi = l2cap_pi(sk); + int err; + + lock_sock(sk); + +- if (l2cap_pi(sk)->rx_busy_skb) { ++ if (chan->mode == L2CAP_MODE_ERTM && !list_empty(&pi->rx_busy)) { + err = -ENOMEM; + goto done; + } + + if (chan->mode != L2CAP_MODE_ERTM && +- chan->mode != L2CAP_MODE_STREAMING) { ++ chan->mode != L2CAP_MODE_STREAMING && ++ chan->mode != L2CAP_MODE_LE_FLOWCTL && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) { + /* Even if no filter is attached, we could potentially + * get errors from security modules, etc. + */ +@@ -1470,7 +1506,9 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) + + err = __sock_queue_rcv_skb(sk, skb); + +- /* For ERTM, handle one skb that doesn't fit into the recv ++ l2cap_publish_rx_avail(chan); ++ ++ /* For ERTM and LE, handle a skb that doesn't fit into the recv + * buffer. This is important to do because the data frames + * have already been acked, so the skb cannot be discarded. + * +@@ -1479,8 +1517,18 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) + * acked and reassembled until there is buffer space + * available. + */ +- if (err < 0 && chan->mode == L2CAP_MODE_ERTM) { +- l2cap_pi(sk)->rx_busy_skb = skb; ++ if (err < 0 && ++ (chan->mode == L2CAP_MODE_ERTM || ++ chan->mode == L2CAP_MODE_LE_FLOWCTL || ++ chan->mode == L2CAP_MODE_EXT_FLOWCTL)) { ++ struct l2cap_rx_busy *rx_busy = ++ kmalloc(sizeof(*rx_busy), GFP_KERNEL); ++ if (!rx_busy) { ++ err = -ENOMEM; ++ goto done; ++ } ++ rx_busy->skb = skb; ++ list_add_tail(&rx_busy->list, &pi->rx_busy); + l2cap_chan_busy(chan, 1); + err = 0; + } +@@ -1706,6 +1754,8 @@ static const struct l2cap_ops l2cap_chan_ops = { + + static void l2cap_sock_destruct(struct sock *sk) + { ++ struct l2cap_rx_busy *rx_busy, *next; ++ + BT_DBG("sk %p", sk); + + if (l2cap_pi(sk)->chan) { +@@ -1713,9 +1763,10 @@ static void l2cap_sock_destruct(struct sock *sk) + l2cap_chan_put(l2cap_pi(sk)->chan); + } + +- if (l2cap_pi(sk)->rx_busy_skb) { +- kfree_skb(l2cap_pi(sk)->rx_busy_skb); +- l2cap_pi(sk)->rx_busy_skb = NULL; ++ list_for_each_entry_safe(rx_busy, next, &l2cap_pi(sk)->rx_busy, list) { ++ kfree_skb(rx_busy->skb); ++ list_del(&rx_busy->list); ++ kfree(rx_busy); + } + + skb_queue_purge(&sk->sk_receive_queue); +@@ -1799,6 +1850,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) + + chan->data = sk; + chan->ops = &l2cap_chan_ops; ++ ++ l2cap_publish_rx_avail(chan); + } + + static struct proto l2cap_proto = { +@@ -1820,6 +1873,8 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, + sk->sk_destruct = l2cap_sock_destruct; + sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT; + ++ INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy); ++ + chan = l2cap_chan_create(); + if (!chan) { + sk_free(sk); +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 965f621ef865a..80f220b7e19d5 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -443,8 +443,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, + + count = 0; + list_for_each_entry(d, &hci_dev_list, list) { +- if (d->dev_type == HCI_PRIMARY && +- !hci_dev_test_flag(d, HCI_UNCONFIGURED)) ++ if (!hci_dev_test_flag(d, HCI_UNCONFIGURED)) + count++; + } + +@@ -468,8 +467,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, + if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) + continue; + +- if (d->dev_type == HCI_PRIMARY && +- !hci_dev_test_flag(d, HCI_UNCONFIGURED)) { ++ if (!hci_dev_test_flag(d, HCI_UNCONFIGURED)) { + rp->index[count++] = cpu_to_le16(d->id); + bt_dev_dbg(hdev, "Added hci%u", d->id); + } +@@ -503,8 +501,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, + + count = 0; + list_for_each_entry(d, &hci_dev_list, list) { +- if (d->dev_type == HCI_PRIMARY && +- hci_dev_test_flag(d, HCI_UNCONFIGURED)) ++ if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) + count++; + } + +@@ -528,8 +525,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, + if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) + continue; + +- if (d->dev_type == HCI_PRIMARY && +- hci_dev_test_flag(d, HCI_UNCONFIGURED)) { ++ if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) { + rp->index[count++] = cpu_to_le16(d->id); + bt_dev_dbg(hdev, "Added hci%u", d->id); + } +@@ -561,10 +557,8 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev, + read_lock(&hci_dev_list_lock); + + count = 0; +- list_for_each_entry(d, &hci_dev_list, list) { +- if (d->dev_type == HCI_PRIMARY || d->dev_type == HCI_AMP) +- count++; +- } ++ list_for_each_entry(d, &hci_dev_list, list) ++ count++; + + rp = kmalloc(struct_size(rp, entry, count), GFP_ATOMIC); + if (!rp) { +@@ -585,16 +579,10 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev, + if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) + continue; + +- if (d->dev_type == HCI_PRIMARY) { +- if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) +- rp->entry[count].type = 0x01; +- else +- rp->entry[count].type = 0x00; +- } else if (d->dev_type == HCI_AMP) { +- rp->entry[count].type = 0x02; +- } else { +- continue; +- } ++ if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) ++ rp->entry[count].type = 0x01; ++ else ++ rp->entry[count].type = 0x00; + + rp->entry[count].bus = d->bus; + rp->entry[count++].index = cpu_to_le16(d->id); +@@ -9331,23 +9319,14 @@ void mgmt_index_added(struct hci_dev *hdev) + if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) + return; + +- switch (hdev->dev_type) { +- case HCI_PRIMARY: +- if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { +- mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, +- NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS); +- ev.type = 0x01; +- } else { +- mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, +- HCI_MGMT_INDEX_EVENTS); +- ev.type = 0x00; +- } +- break; +- case HCI_AMP: +- ev.type = 0x02; +- break; +- default: +- return; ++ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { ++ mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, ++ HCI_MGMT_UNCONF_INDEX_EVENTS); ++ ev.type = 0x01; ++ } else { ++ mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, ++ HCI_MGMT_INDEX_EVENTS); ++ ev.type = 0x00; + } + + ev.bus = hdev->bus; +@@ -9364,25 +9343,16 @@ void mgmt_index_removed(struct hci_dev *hdev) + if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) + return; + +- switch (hdev->dev_type) { +- case HCI_PRIMARY: +- mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status); ++ mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status); + +- if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { +- mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, +- NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS); +- ev.type = 0x01; +- } else { +- mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, +- HCI_MGMT_INDEX_EVENTS); +- ev.type = 0x00; +- } +- break; +- case HCI_AMP: +- ev.type = 0x02; +- break; +- default: +- return; ++ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { ++ mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, ++ HCI_MGMT_UNCONF_INDEX_EVENTS); ++ ev.type = 0x01; ++ } else { ++ mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, ++ HCI_MGMT_INDEX_EVENTS); ++ ev.type = 0x00; + } + + ev.bus = hdev->bus; +diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c +index c366ccc8b3db7..ecac7886988b1 100644 +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -27,6 +27,7 @@ EXPORT_SYMBOL_GPL(nf_br_ops); + /* net device transmit always called with BH disabled */ + netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) + { ++ enum skb_drop_reason reason = pskb_may_pull_reason(skb, ETH_HLEN); + struct net_bridge_mcast_port *pmctx_null = NULL; + struct net_bridge *br = netdev_priv(dev); + struct net_bridge_mcast *brmctx = &br->multicast_ctx; +@@ -38,6 +39,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) + const unsigned char *dest; + u16 vid = 0; + ++ if (unlikely(reason != SKB_NOT_DROPPED_YET)) { ++ kfree_skb_reason(skb, reason); ++ return NETDEV_TX_OK; ++ } ++ + memset(skb->cb, 0, sizeof(struct br_input_skb_cb)); + br_tc_skb_miss_set(skb, false); + +diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c +index ee680adcee179..3c66141d34d62 100644 +--- a/net/bridge/br_mst.c ++++ b/net/bridge/br_mst.c +@@ -78,7 +78,7 @@ static void br_mst_vlan_set_state(struct net_bridge_port *p, struct net_bridge_v + { + struct net_bridge_vlan_group *vg = nbp_vlan_group(p); + +- if (v->state == state) ++ if (br_vlan_get_state(v) == state) + return; + + br_vlan_set_state(v, state); +@@ -100,11 +100,12 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state, + }; + struct net_bridge_vlan_group *vg; + struct net_bridge_vlan *v; +- int err; ++ int err = 0; + ++ rcu_read_lock(); + vg = nbp_vlan_group(p); + if (!vg) +- return 0; ++ goto out; + + /* MSTI 0 (CST) state changes are notified via the regular + * SWITCHDEV_ATTR_ID_PORT_STP_STATE. +@@ -112,17 +113,20 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state, + if (msti) { + err = switchdev_port_attr_set(p->dev, &attr, extack); + if (err && err != -EOPNOTSUPP) +- return err; ++ goto out; + } + +- list_for_each_entry(v, &vg->vlan_list, vlist) { ++ err = 0; ++ list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { + if (v->brvlan->msti != msti) + continue; + + br_mst_vlan_set_state(p, v, state); + } + +- return 0; ++out: ++ rcu_read_unlock(); ++ return err; + } + + static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti) +diff --git a/net/core/dev.c b/net/core/dev.c +index 331848eca7d31..e8fb4ef8a85f8 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -10488,8 +10488,9 @@ static struct net_device *netdev_wait_allrefs_any(struct list_head *list) + rebroadcast_time = jiffies; + } + ++ rcu_barrier(); ++ + if (!wait) { +- rcu_barrier(); + wait = WAIT_REFS_MIN_MSECS; + } else { + msleep(wait); +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index 7a437f0d41905..7e45c34c8340a 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -1683,6 +1683,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, const struct in_ifaddr *ifa, + struct nlmsghdr *nlh; + unsigned long tstamp; + u32 preferred, valid; ++ u32 flags; + + nlh = nlmsg_put(skb, args->portid, args->seq, args->event, sizeof(*ifm), + args->flags); +@@ -1692,7 +1693,13 @@ static int inet_fill_ifaddr(struct sk_buff *skb, const struct in_ifaddr *ifa, + ifm = nlmsg_data(nlh); + ifm->ifa_family = AF_INET; + ifm->ifa_prefixlen = ifa->ifa_prefixlen; +- ifm->ifa_flags = READ_ONCE(ifa->ifa_flags); ++ ++ flags = READ_ONCE(ifa->ifa_flags); ++ /* Warning : ifm->ifa_flags is an __u8, it holds only 8 bits. ++ * The 32bit value is given in IFA_FLAGS attribute. ++ */ ++ ifm->ifa_flags = (__u8)flags; ++ + ifm->ifa_scope = ifa->ifa_scope; + ifm->ifa_index = ifa->ifa_dev->dev->ifindex; + +@@ -1701,7 +1708,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, const struct in_ifaddr *ifa, + goto nla_put_failure; + + tstamp = READ_ONCE(ifa->ifa_tstamp); +- if (!(ifm->ifa_flags & IFA_F_PERMANENT)) { ++ if (!(flags & IFA_F_PERMANENT)) { + preferred = READ_ONCE(ifa->ifa_preferred_lft); + valid = READ_ONCE(ifa->ifa_valid_lft); + if (preferred != INFINITY_LIFE_TIME) { +@@ -1732,7 +1739,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, const struct in_ifaddr *ifa, + nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) || + (ifa->ifa_proto && + nla_put_u8(skb, IFA_PROTO, ifa->ifa_proto)) || +- nla_put_u32(skb, IFA_FLAGS, ifm->ifa_flags) || ++ nla_put_u32(skb, IFA_FLAGS, flags) || + (ifa->ifa_rt_priority && + nla_put_u32(skb, IFA_RT_PRIORITY, ifa->ifa_rt_priority)) || + put_cacheinfo(skb, READ_ONCE(ifa->ifa_cstamp), tstamp, +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index e0cef75f85fb9..92511b7fd5249 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -2001,7 +2001,7 @@ int tcp_v4_early_demux(struct sk_buff *skb) + bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb, + enum skb_drop_reason *reason) + { +- u32 limit, tail_gso_size, tail_gso_segs; ++ u32 tail_gso_size, tail_gso_segs; + struct skb_shared_info *shinfo; + const struct tcphdr *th; + struct tcphdr *thtail; +@@ -2010,6 +2010,7 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb, + bool fragstolen; + u32 gso_segs; + u32 gso_size; ++ u64 limit; + int delta; + + /* In case all data was pulled from skb frags (in __pskb_pull_tail()), +@@ -2107,7 +2108,13 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb, + __skb_push(skb, hdrlen); + + no_coalesce: +- limit = (u32)READ_ONCE(sk->sk_rcvbuf) + (u32)(READ_ONCE(sk->sk_sndbuf) >> 1); ++ /* sk->sk_backlog.len is reset only at the end of __release_sock(). ++ * Both sk->sk_backlog.len and sk->sk_rmem_alloc could reach ++ * sk_rcvbuf in normal conditions. ++ */ ++ limit = ((u64)READ_ONCE(sk->sk_rcvbuf)) << 1; ++ ++ limit += ((u32)READ_ONCE(sk->sk_sndbuf)) >> 1; + + /* Only socket owner can try to collapse/prune rx queues + * to reduce memory overhead, so add a little headroom here. +@@ -2115,6 +2122,8 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb, + */ + limit += 64 * 1024; + ++ limit = min_t(u64, limit, UINT_MAX); ++ + if (unlikely(sk_add_backlog(sk, skb, limit))) { + bh_unlock_sock(sk); + *reason = SKB_DROP_REASON_SOCKET_BACKLOG; +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index b32cf2eeeb41d..b5ad0c527c521 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -427,15 +427,21 @@ static struct sock *udp4_lib_lookup2(struct net *net, + { + struct sock *sk, *result; + int score, badness; ++ bool need_rescore; + + result = NULL; + badness = 0; + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { +- score = compute_score(sk, net, saddr, sport, +- daddr, hnum, dif, sdif); ++ need_rescore = false; ++rescore: ++ score = compute_score(need_rescore ? result : sk, net, saddr, ++ sport, daddr, hnum, dif, sdif); + if (score > badness) { + badness = score; + ++ if (need_rescore) ++ continue; ++ + if (sk->sk_state == TCP_ESTABLISHED) { + result = sk; + continue; +@@ -456,9 +462,14 @@ static struct sock *udp4_lib_lookup2(struct net *net, + if (IS_ERR(result)) + continue; + +- badness = compute_score(result, net, saddr, sport, +- daddr, hnum, dif, sdif); +- ++ /* compute_score is too long of a function to be ++ * inlined, and calling it again here yields ++ * measureable overhead for some ++ * workloads. Work around it by jumping ++ * backwards to rescore 'result'. ++ */ ++ need_rescore = true; ++ goto rescore; + } + } + return result; +diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c +index acb4f119e11f0..148bf9e3131a1 100644 +--- a/net/ipv6/reassembly.c ++++ b/net/ipv6/reassembly.c +@@ -369,7 +369,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) + * the source of the fragment, with the Pointer field set to zero. + */ + nexthdr = hdr->nexthdr; +- if (ipv6frag_thdr_truncated(skb, skb_transport_offset(skb), &nexthdr)) { ++ if (ipv6frag_thdr_truncated(skb, skb_network_offset(skb) + sizeof(struct ipv6hdr), &nexthdr)) { + __IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev), + IPSTATS_MIB_INHDRERRORS); + icmpv6_param_prob(skb, ICMPV6_HDR_INCOMP, 0); +diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c +index 35508abd76f43..a31521e270f78 100644 +--- a/net/ipv6/seg6.c ++++ b/net/ipv6/seg6.c +@@ -551,6 +551,8 @@ int __init seg6_init(void) + #endif + #ifdef CONFIG_IPV6_SEG6_LWTUNNEL + out_unregister_genl: ++#endif ++#if IS_ENABLED(CONFIG_IPV6_SEG6_LWTUNNEL) || IS_ENABLED(CONFIG_IPV6_SEG6_HMAC) + genl_unregister_family(&seg6_genl_family); + #endif + out_unregister_pernet: +@@ -564,8 +566,9 @@ void seg6_exit(void) + seg6_hmac_exit(); + #endif + #ifdef CONFIG_IPV6_SEG6_LWTUNNEL ++ seg6_local_exit(); + seg6_iptunnel_exit(); + #endif +- unregister_pernet_subsys(&ip6_segments_ops); + genl_unregister_family(&seg6_genl_family); ++ unregister_pernet_subsys(&ip6_segments_ops); + } +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 8f7aa8bac1e7b..e0dd5bc2b30eb 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -168,15 +168,21 @@ static struct sock *udp6_lib_lookup2(struct net *net, + { + struct sock *sk, *result; + int score, badness; ++ bool need_rescore; + + result = NULL; + badness = -1; + udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { +- score = compute_score(sk, net, saddr, sport, +- daddr, hnum, dif, sdif); ++ need_rescore = false; ++rescore: ++ score = compute_score(need_rescore ? result : sk, net, saddr, ++ sport, daddr, hnum, dif, sdif); + if (score > badness) { + badness = score; + ++ if (need_rescore) ++ continue; ++ + if (sk->sk_state == TCP_ESTABLISHED) { + result = sk; + continue; +@@ -197,8 +203,14 @@ static struct sock *udp6_lib_lookup2(struct net *net, + if (IS_ERR(result)) + continue; + +- badness = compute_score(sk, net, saddr, sport, +- daddr, hnum, dif, sdif); ++ /* compute_score is too long of a function to be ++ * inlined, and calling it again here yields ++ * measureable overhead for some ++ * workloads. Work around it by jumping ++ * backwards to rescore 'result'. ++ */ ++ need_rescore = true; ++ goto rescore; + } + } + return result; +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index 8d21ff25f1602..4a0fb8731eee9 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -887,22 +887,20 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb) + return 1; + } + +-/* UDP encapsulation receive handler. See net/ipv4/udp.c. +- * Return codes: +- * 0 : success. +- * <0: error +- * >0: skb should be passed up to userspace as UDP. ++/* UDP encapsulation receive and error receive handlers. ++ * See net/ipv4/udp.c for details. ++ * ++ * Note that these functions are called from inside an ++ * RCU-protected region, but without the socket being locked. ++ * ++ * Hence we use rcu_dereference_sk_user_data to access the ++ * tunnel data structure rather the usual l2tp_sk_to_tunnel ++ * accessor function. + */ + int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) + { + struct l2tp_tunnel *tunnel; + +- /* Note that this is called from the encap_rcv hook inside an +- * RCU-protected region, but without the socket being locked. +- * Hence we use rcu_dereference_sk_user_data to access the +- * tunnel data structure rather the usual l2tp_sk_to_tunnel +- * accessor function. +- */ + tunnel = rcu_dereference_sk_user_data(sk); + if (!tunnel) + goto pass_up; +@@ -919,6 +917,29 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb) + } + EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv); + ++static void l2tp_udp_encap_err_recv(struct sock *sk, struct sk_buff *skb, int err, ++ __be16 port, u32 info, u8 *payload) ++{ ++ struct l2tp_tunnel *tunnel; ++ ++ tunnel = rcu_dereference_sk_user_data(sk); ++ if (!tunnel || tunnel->fd < 0) ++ return; ++ ++ sk->sk_err = err; ++ sk_error_report(sk); ++ ++ if (ip_hdr(skb)->version == IPVERSION) { ++ if (inet_test_bit(RECVERR, sk)) ++ return ip_icmp_error(sk, skb, err, port, info, payload); ++#if IS_ENABLED(CONFIG_IPV6) ++ } else { ++ if (inet6_test_bit(RECVERR6, sk)) ++ return ipv6_icmp_error(sk, skb, err, port, info, payload); ++#endif ++ } ++} ++ + /************************************************************************ + * Transmit handling + ***********************************************************************/ +@@ -1493,6 +1514,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + .sk_user_data = tunnel, + .encap_type = UDP_ENCAP_L2TPINUDP, + .encap_rcv = l2tp_udp_encap_recv, ++ .encap_err_rcv = l2tp_udp_encap_err_recv, + .encap_destroy = l2tp_udp_encap_destroy, + }; + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index f67c1d0218121..07abaf7820c56 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1607,10 +1607,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, + /* abort any running channel switch or color change */ + link_conf->csa_active = false; + link_conf->color_change_active = false; +- if (sdata->csa_blocked_tx) { ++ if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = false; ++ sdata->csa_blocked_queues = false; + } + + ieee80211_free_next_beacon(link); +@@ -3648,7 +3648,7 @@ void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_t + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; + +- sdata->csa_blocked_tx = block_tx; ++ sdata->csa_blocked_queues = block_tx; + sdata_info(sdata, "channel switch failed, disconnecting\n"); + wiphy_work_queue(local->hw.wiphy, &ifmgd->csa_connection_drop_work); + } +@@ -3734,10 +3734,10 @@ static int __ieee80211_csa_finalize(struct ieee80211_link_data *link_data) + + ieee80211_link_info_change_notify(sdata, link_data, changed); + +- if (sdata->csa_blocked_tx) { ++ if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = false; ++ sdata->csa_blocked_queues = false; + } + + err = drv_post_channel_switch(link_data); +@@ -4019,7 +4019,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA)) { + ieee80211_stop_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = true; ++ sdata->csa_blocked_queues = true; + } + + cfg80211_ch_switch_started_notify(sdata->dev, +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index bd507d6b65e3f..70c67c860e995 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -974,6 +974,7 @@ struct ieee80211_link_data_managed { + + bool csa_waiting_bcn; + bool csa_ignored_same_chan; ++ bool csa_blocked_tx; + struct wiphy_delayed_work chswitch_work; + + struct wiphy_work request_smps_work; +@@ -1092,7 +1093,7 @@ struct ieee80211_sub_if_data { + + unsigned long state; + +- bool csa_blocked_tx; ++ bool csa_blocked_queues; + + char name[IFNAMSIZ]; + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 395de62d9cb2d..ef6b0fc82d022 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -544,10 +544,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + sdata->vif.bss_conf.csa_active = false; + if (sdata->vif.type == NL80211_IFTYPE_STATION) + sdata->deflink.u.mgd.csa_waiting_bcn = false; +- if (sdata->csa_blocked_tx) { ++ if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = false; ++ sdata->csa_blocked_queues = false; + } + + wiphy_work_cancel(local->hw.wiphy, &sdata->deflink.csa_finalize_work); +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 3bbb216a0fc8c..497677e3d8b27 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1933,13 +1933,14 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_link_data *link) + + WARN_ON(!link->conf->csa_active); + +- if (sdata->csa_blocked_tx) { ++ if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = false; ++ sdata->csa_blocked_queues = false; + } + + link->conf->csa_active = false; ++ link->u.mgd.csa_blocked_tx = false; + link->u.mgd.csa_waiting_bcn = false; + + ret = drv_post_channel_switch(link); +@@ -1999,13 +2000,14 @@ ieee80211_sta_abort_chanswitch(struct ieee80211_link_data *link) + + ieee80211_link_unreserve_chanctx(link); + +- if (sdata->csa_blocked_tx) { ++ if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = false; ++ sdata->csa_blocked_queues = false; + } + + link->conf->csa_active = false; ++ link->u.mgd.csa_blocked_tx = false; + + drv_abort_channel_switch(link); + } +@@ -2165,12 +2167,13 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, + link->csa_chanreq = csa_ie.chanreq; + link->u.mgd.csa_ignored_same_chan = false; + link->u.mgd.beacon_crc_valid = false; ++ link->u.mgd.csa_blocked_tx = csa_ie.mode; + + if (csa_ie.mode && + !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA)) { + ieee80211_stop_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = true; ++ sdata->csa_blocked_queues = true; + } + + cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper, +@@ -2199,7 +2202,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, + * reset when the disconnection worker runs. + */ + link->conf->csa_active = true; +- sdata->csa_blocked_tx = ++ link->u.mgd.csa_blocked_tx = csa_ie.mode; ++ sdata->csa_blocked_queues = + csa_ie.mode && !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA); + + wiphy_work_queue(sdata->local->hw.wiphy, +@@ -3252,12 +3256,13 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, + } + + sdata->vif.bss_conf.csa_active = false; ++ sdata->deflink.u.mgd.csa_blocked_tx = false; + sdata->deflink.u.mgd.csa_waiting_bcn = false; + sdata->deflink.u.mgd.csa_ignored_same_chan = false; +- if (sdata->csa_blocked_tx) { ++ if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = false; ++ sdata->csa_blocked_queues = false; + } + + /* existing TX TSPEC sessions no longer exist */ +@@ -3563,19 +3568,32 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; +- bool tx; ++ bool tx = false; + + lockdep_assert_wiphy(local->hw.wiphy); + + if (!ifmgd->associated) + return; + +- /* +- * MLO drivers should have HANDLES_QUIET_CSA, so that csa_blocked_tx +- * is always false; if they don't then this may try to transmit the +- * frame but queues will be stopped. +- */ +- tx = !sdata->csa_blocked_tx; ++ /* only transmit if we have a link that makes that worthwhile */ ++ for (unsigned int link_id = 0; ++ link_id < ARRAY_SIZE(sdata->link); ++ link_id++) { ++ struct ieee80211_link_data *link; ++ ++ if (!ieee80211_vif_link_active(&sdata->vif, link_id)) ++ continue; ++ ++ link = sdata_dereference(sdata->link[link_id], sdata); ++ if (WARN_ON_ONCE(!link)) ++ continue; ++ ++ if (link->u.mgd.csa_blocked_tx) ++ continue; ++ ++ tx = true; ++ break; ++ } + + if (!ifmgd->driver_disconnect) { + unsigned int link_id; +@@ -3608,10 +3626,11 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) + /* the other links will be destroyed */ + sdata->vif.bss_conf.csa_active = false; + sdata->deflink.u.mgd.csa_waiting_bcn = false; +- if (sdata->csa_blocked_tx) { ++ sdata->deflink.u.mgd.csa_blocked_tx = false; ++ if (sdata->csa_blocked_queues) { + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_blocked_tx = false; ++ sdata->csa_blocked_queues = false; + } + + ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx, +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 73850312580f7..3da1c5c450358 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -708,19 +708,11 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, + return -EBUSY; + + /* For an MLO connection, if a link ID was specified, validate that it +- * is indeed active. If no link ID was specified, select one of the +- * active links. ++ * is indeed active. + */ +- if (ieee80211_vif_is_mld(&sdata->vif)) { +- if (req->tsf_report_link_id >= 0) { +- if (!(sdata->vif.active_links & +- BIT(req->tsf_report_link_id))) +- return -EINVAL; +- } else { +- req->tsf_report_link_id = +- __ffs(sdata->vif.active_links); +- } +- } ++ if (ieee80211_vif_is_mld(&sdata->vif) && req->tsf_report_link_id >= 0 && ++ !(sdata->vif.active_links & BIT(req->tsf_report_link_id))) ++ return -EINVAL; + + if (!__ieee80211_can_leave_ch(sdata)) + return -EBUSY; +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index a10ebf3ee10a1..9d1ee199490bb 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -308,6 +308,9 @@ struct mptcp_sock { + free_first:1, + rcvspace_init:1; + u32 notsent_lowat; ++ int keepalive_cnt; ++ int keepalive_idle; ++ int keepalive_intvl; + struct work_struct work; + struct sk_buff *ooo_last_skb; + struct rb_root out_of_order_queue; +diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c +index 73fdf423de44e..19ee684f9e401 100644 +--- a/net/mptcp/sockopt.c ++++ b/net/mptcp/sockopt.c +@@ -181,8 +181,6 @@ static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname, + + switch (optname) { + case SO_KEEPALIVE: +- mptcp_sol_socket_sync_intval(msk, optname, val); +- return 0; + case SO_DEBUG: + case SO_MARK: + case SO_PRIORITY: +@@ -624,6 +622,31 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t + return ret; + } + ++static int __mptcp_setsockopt_set_val(struct mptcp_sock *msk, int max, ++ int (*set_val)(struct sock *, int), ++ int *msk_val, int val) ++{ ++ struct mptcp_subflow_context *subflow; ++ int err = 0; ++ ++ mptcp_for_each_subflow(msk, subflow) { ++ struct sock *ssk = mptcp_subflow_tcp_sock(subflow); ++ int ret; ++ ++ lock_sock(ssk); ++ ret = set_val(ssk, val); ++ err = err ? : ret; ++ release_sock(ssk); ++ } ++ ++ if (!err) { ++ *msk_val = val; ++ sockopt_seq_inc(msk); ++ } ++ ++ return err; ++} ++ + static int __mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, int val) + { + struct mptcp_subflow_context *subflow; +@@ -820,6 +843,22 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname, + case TCP_NODELAY: + ret = __mptcp_setsockopt_sol_tcp_nodelay(msk, val); + break; ++ case TCP_KEEPIDLE: ++ ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPIDLE, ++ &tcp_sock_set_keepidle_locked, ++ &msk->keepalive_idle, val); ++ break; ++ case TCP_KEEPINTVL: ++ ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPINTVL, ++ &tcp_sock_set_keepintvl, ++ &msk->keepalive_intvl, val); ++ break; ++ case TCP_KEEPCNT: ++ ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPCNT, ++ &tcp_sock_set_keepcnt, ++ &msk->keepalive_cnt, ++ val); ++ break; + default: + ret = -ENOPROTOOPT; + } +@@ -1322,6 +1361,8 @@ static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval, + static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, + char __user *optval, int __user *optlen) + { ++ struct sock *sk = (void *)msk; ++ + switch (optname) { + case TCP_ULP: + case TCP_CONGESTION: +@@ -1340,6 +1381,18 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, + return mptcp_put_int_option(msk, optval, optlen, msk->cork); + case TCP_NODELAY: + return mptcp_put_int_option(msk, optval, optlen, msk->nodelay); ++ case TCP_KEEPIDLE: ++ return mptcp_put_int_option(msk, optval, optlen, ++ msk->keepalive_idle ? : ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_time) / HZ); ++ case TCP_KEEPINTVL: ++ return mptcp_put_int_option(msk, optval, optlen, ++ msk->keepalive_intvl ? : ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_intvl) / HZ); ++ case TCP_KEEPCNT: ++ return mptcp_put_int_option(msk, optval, optlen, ++ msk->keepalive_cnt ? : ++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_probes)); + case TCP_NOTSENT_LOWAT: + return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat); + } +@@ -1457,6 +1510,9 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk) + tcp_set_congestion_control(ssk, msk->ca_name, false, true); + __tcp_sock_set_cork(ssk, !!msk->cork); + __tcp_sock_set_nodelay(ssk, !!msk->nodelay); ++ tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle); ++ tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl); ++ tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt); + + inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk)); + inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk)); +diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c +index 70480869ad1c5..bd2b17b219ae9 100644 +--- a/net/netrom/nr_route.c ++++ b/net/netrom/nr_route.c +@@ -285,22 +285,14 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic, + return 0; + } + +-static inline void __nr_remove_node(struct nr_node *nr_node) ++static void nr_remove_node_locked(struct nr_node *nr_node) + { ++ lockdep_assert_held(&nr_node_list_lock); ++ + hlist_del_init(&nr_node->node_node); + nr_node_put(nr_node); + } + +-#define nr_remove_node_locked(__node) \ +- __nr_remove_node(__node) +- +-static void nr_remove_node(struct nr_node *nr_node) +-{ +- spin_lock_bh(&nr_node_list_lock); +- __nr_remove_node(nr_node); +- spin_unlock_bh(&nr_node_list_lock); +-} +- + static inline void __nr_remove_neigh(struct nr_neigh *nr_neigh) + { + hlist_del_init(&nr_neigh->neigh_node); +@@ -339,6 +331,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n + return -EINVAL; + } + ++ spin_lock_bh(&nr_node_list_lock); + nr_node_lock(nr_node); + for (i = 0; i < nr_node->count; i++) { + if (nr_node->routes[i].neighbour == nr_neigh) { +@@ -352,7 +345,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n + nr_node->count--; + + if (nr_node->count == 0) { +- nr_remove_node(nr_node); ++ nr_remove_node_locked(nr_node); + } else { + switch (i) { + case 0: +@@ -367,12 +360,14 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n + nr_node_put(nr_node); + } + nr_node_unlock(nr_node); ++ spin_unlock_bh(&nr_node_list_lock); + + return 0; + } + } + nr_neigh_put(nr_neigh); + nr_node_unlock(nr_node); ++ spin_unlock_bh(&nr_node_list_lock); + nr_node_put(nr_node); + + return -EINVAL; +diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c +index 33b21a0c05481..8a848ce72e291 100644 +--- a/net/openvswitch/flow.c ++++ b/net/openvswitch/flow.c +@@ -561,7 +561,6 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, + */ + key->tp.src = htons(icmp->icmp6_type); + key->tp.dst = htons(icmp->icmp6_code); +- memset(&key->ipv6.nd, 0, sizeof(key->ipv6.nd)); + + if (icmp->icmp6_code == 0 && + (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION || +@@ -570,6 +569,8 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, + struct nd_msg *nd; + int offset; + ++ memset(&key->ipv6.nd, 0, sizeof(key->ipv6.nd)); ++ + /* In order to process neighbor discovery options, we need the + * entire packet. + */ +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 18f616f487eaa..150451ddd7553 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2522,8 +2522,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb) + ts = __packet_set_timestamp(po, ph, skb); + __packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts); + +- if (!packet_read_pending(&po->tx_ring)) +- complete(&po->skb_completion); ++ complete(&po->skb_completion); + } + + sock_wfree(skb); +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index abb0c70ffc8b0..654a3cc0d3479 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -725,6 +725,24 @@ int qrtr_ns_init(void) + if (ret < 0) + goto err_wq; + ++ /* As the qrtr ns socket owner and creator is the same module, we have ++ * to decrease the qrtr module reference count to guarantee that it ++ * remains zero after the ns socket is created, otherwise, executing ++ * "rmmod" command is unable to make the qrtr module deleted after the ++ * qrtr module is inserted successfully. ++ * ++ * However, the reference count is increased twice in ++ * sock_create_kern(): one is to increase the reference count of owner ++ * of qrtr socket's proto_ops struct; another is to increment the ++ * reference count of owner of qrtr proto struct. Therefore, we must ++ * decrement the module reference count twice to ensure that it keeps ++ * zero after server's listening socket is created. Of course, we ++ * must bump the module reference count twice as well before the socket ++ * is closed. ++ */ ++ module_put(qrtr_ns.sock->ops->owner); ++ module_put(qrtr_ns.sock->sk->sk_prot_creator->owner); ++ + return 0; + + err_wq: +@@ -739,6 +757,15 @@ void qrtr_ns_remove(void) + { + cancel_work_sync(&qrtr_ns.work); + destroy_workqueue(qrtr_ns.workqueue); ++ ++ /* sock_release() expects the two references that were put during ++ * qrtr_ns_init(). This function is only called during module remove, ++ * so try_stop_module() has already set the refcnt to 0. Use ++ * __module_get() instead of try_module_get() to successfully take two ++ * references. ++ */ ++ __module_get(qrtr_ns.sock->ops->owner); ++ __module_get(qrtr_ns.sock->sk->sk_prot_creator->owner); + sock_release(qrtr_ns.sock); + } + EXPORT_SYMBOL_GPL(qrtr_ns_remove); +diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c +index 24de941847003..96ab50eda9c2e 100644 +--- a/net/sunrpc/auth_gss/svcauth_gss.c ++++ b/net/sunrpc/auth_gss/svcauth_gss.c +@@ -1033,17 +1033,11 @@ svcauth_gss_proc_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, + + static void gss_free_in_token_pages(struct gssp_in_token *in_token) + { +- u32 inlen; + int i; + + i = 0; +- inlen = in_token->page_len; +- while (inlen) { +- if (in_token->pages[i]) +- put_page(in_token->pages[i]); +- inlen -= inlen > PAGE_SIZE ? PAGE_SIZE : inlen; +- } +- ++ while (in_token->pages[i]) ++ put_page(in_token->pages[i++]); + kfree(in_token->pages); + in_token->pages = NULL; + } +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index b33e429336fb7..2b4b1276d4e86 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -1265,8 +1265,6 @@ svc_generic_init_request(struct svc_rqst *rqstp, + if (rqstp->rq_proc >= versp->vs_nproc) + goto err_bad_proc; + rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc]; +- if (!procp) +- goto err_bad_proc; + + /* Initialize storage for argp and resp */ + memset(rqstp->rq_argp, 0, procp->pc_argzero); +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 9a6ad5974dff5..e94839d89b09d 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2270,7 +2270,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, + goto out_err; + } + +- if (sk->sk_shutdown & SEND_SHUTDOWN) ++ if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) + goto pipe_err; + + while (sent < len) { +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 30ff9a4708134..65c416e8d25eb 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -9162,6 +9162,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + struct wiphy *wiphy; + int err, tmp, n_ssids = 0, n_channels, i; + size_t ie_len, size; ++ size_t ssids_offset, ie_offset; + + wiphy = &rdev->wiphy; + +@@ -9207,21 +9208,20 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) + return -EINVAL; + + size = struct_size(request, channels, n_channels); ++ ssids_offset = size; + size = size_add(size, array_size(sizeof(*request->ssids), n_ssids)); ++ ie_offset = size; + size = size_add(size, ie_len); + request = kzalloc(size, GFP_KERNEL); + if (!request) + return -ENOMEM; ++ request->n_channels = n_channels; + + if (n_ssids) +- request->ssids = (void *)&request->channels[n_channels]; ++ request->ssids = (void *)request + ssids_offset; + request->n_ssids = n_ssids; +- if (ie_len) { +- if (n_ssids) +- request->ie = (void *)(request->ssids + n_ssids); +- else +- request->ie = (void *)(request->channels + n_channels); +- } ++ if (ie_len) ++ request->ie = (void *)request + ie_offset; + + i = 0; + if (scan_freqs) { +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 5a5dd3ce497fc..9b0dbcd6cf79a 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -2207,12 +2207,16 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, + tmp.pub.use_for = data->use_for; + tmp.pub.cannot_use_reasons = data->cannot_use_reasons; + +- if (data->bss_source != BSS_SOURCE_DIRECT) { ++ switch (data->bss_source) { ++ case BSS_SOURCE_MBSSID: + tmp.pub.transmitted_bss = data->source_bss; ++ fallthrough; ++ case BSS_SOURCE_STA_PROFILE: + ts = bss_from_pub(data->source_bss)->ts; + tmp.pub.bssid_index = data->bssid_index; + tmp.pub.max_bssid_indicator = data->max_bssid_indicator; +- } else { ++ break; ++ case BSS_SOURCE_DIRECT: + ts = jiffies; + + if (channel->band == NL80211_BAND_60GHZ) { +@@ -2227,6 +2231,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, + regulatory_hint_found_beacon(wiphy, channel, + gfp); + } ++ break; + } + + /* +@@ -2655,6 +2660,7 @@ struct tbtt_info_iter_data { + u8 param_ch_count; + u32 use_for; + u8 mld_id, link_id; ++ bool non_tx; + }; + + static enum cfg80211_rnr_iter_ret +@@ -2665,14 +2671,20 @@ cfg802121_mld_ap_rnr_iter(void *_data, u8 type, + const struct ieee80211_rnr_mld_params *mld_params; + struct tbtt_info_iter_data *data = _data; + u8 link_id; ++ bool non_tx = false; + + if (type == IEEE80211_TBTT_INFO_TYPE_TBTT && + tbtt_info_len >= offsetofend(struct ieee80211_tbtt_info_ge_11, +- mld_params)) +- mld_params = (void *)(tbtt_info + +- offsetof(struct ieee80211_tbtt_info_ge_11, +- mld_params)); +- else if (type == IEEE80211_TBTT_INFO_TYPE_MLD && ++ mld_params)) { ++ const struct ieee80211_tbtt_info_ge_11 *tbtt_info_ge_11 = ++ (void *)tbtt_info; ++ ++ non_tx = (tbtt_info_ge_11->bss_params & ++ (IEEE80211_RNR_TBTT_PARAMS_MULTI_BSSID | ++ IEEE80211_RNR_TBTT_PARAMS_TRANSMITTED_BSSID)) == ++ IEEE80211_RNR_TBTT_PARAMS_MULTI_BSSID; ++ mld_params = &tbtt_info_ge_11->mld_params; ++ } else if (type == IEEE80211_TBTT_INFO_TYPE_MLD && + tbtt_info_len >= sizeof(struct ieee80211_rnr_mld_params)) + mld_params = (void *)tbtt_info; + else +@@ -2691,6 +2703,7 @@ cfg802121_mld_ap_rnr_iter(void *_data, u8 type, + data->param_ch_count = + le16_get_bits(mld_params->params, + IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT); ++ data->non_tx = non_tx; + + if (type == IEEE80211_TBTT_INFO_TYPE_TBTT) + data->use_for = NL80211_BSS_USE_FOR_ALL; +@@ -2702,7 +2715,7 @@ cfg802121_mld_ap_rnr_iter(void *_data, u8 type, + static u8 + cfg80211_rnr_info_for_mld_ap(const u8 *ie, size_t ielen, u8 mld_id, u8 link_id, + const struct ieee80211_neighbor_ap_info **ap_info, +- u8 *param_ch_count) ++ u8 *param_ch_count, bool *non_tx) + { + struct tbtt_info_iter_data data = { + .mld_id = mld_id, +@@ -2713,6 +2726,7 @@ cfg80211_rnr_info_for_mld_ap(const u8 *ie, size_t ielen, u8 mld_id, u8 link_id, + + *ap_info = data.ap_info; + *param_ch_count = data.param_ch_count; ++ *non_tx = data.non_tx; + + return data.use_for; + } +@@ -2892,6 +2906,7 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy, + ssize_t profile_len; + u8 param_ch_count; + u8 link_id, use_for; ++ bool non_tx; + + if (!ieee80211_mle_basic_sta_prof_size_ok((u8 *)mle->sta_prof[i], + mle->sta_prof_len[i])) +@@ -2937,10 +2952,24 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy, + tx_data->ielen, + mld_id, link_id, + &ap_info, +- ¶m_ch_count); ++ ¶m_ch_count, ++ &non_tx); + if (!use_for) + continue; + ++ /* ++ * As of 802.11be_D5.0, the specification does not give us any ++ * way of discovering both the MaxBSSID and the Multiple-BSSID ++ * Index. It does seem like the Multiple-BSSID Index element ++ * may be provided, but section 9.4.2.45 explicitly forbids ++ * including a Multiple-BSSID Element (in this case without any ++ * subelements). ++ * Without both pieces of information we cannot calculate the ++ * reference BSSID, so simply ignore the BSS. ++ */ ++ if (non_tx) ++ continue; ++ + /* We could sanity check the BSSID is included */ + + if (!ieee80211_operating_class_to_band(ap_info->op_class, +diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c +index 32e930c853bba..8b8ecd65c28c4 100644 +--- a/samples/landlock/sandboxer.c ++++ b/samples/landlock/sandboxer.c +@@ -153,7 +153,7 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, + const __u64 allowed_access) + { + int ret = 1; +- char *env_port_name, *strport; ++ char *env_port_name, *env_port_name_next, *strport; + struct landlock_net_port_attr net_port = { + .allowed_access = allowed_access, + .port = 0, +@@ -165,7 +165,8 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, + env_port_name = strdup(env_port_name); + unsetenv(env_var); + +- while ((strport = strsep(&env_port_name, ENV_DELIMITER))) { ++ env_port_name_next = env_port_name; ++ while ((strport = strsep(&env_port_name_next, ENV_DELIMITER))) { + net_port.port = atoi(strport); + if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &net_port, 0)) { +diff --git a/scripts/module.lds.S b/scripts/module.lds.S +index bf5bcf2836d81..89ff01a22634f 100644 +--- a/scripts/module.lds.S ++++ b/scripts/module.lds.S +@@ -13,6 +13,7 @@ SECTIONS { + /DISCARD/ : { + *(.discard) + *(.discard.*) ++ *(.export_symbol) + } + + __ksymtab 0 : { *(SORT(___ksymtab+*)) } +diff --git a/sound/core/init.c b/sound/core/init.c +index 4ed5037d8693b..66d7265fea920 100644 +--- a/sound/core/init.c ++++ b/sound/core/init.c +@@ -313,8 +313,8 @@ static int snd_card_init(struct snd_card *card, struct device *parent, + card->number = idx; + #ifdef MODULE + WARN_ON(!module); +- card->module = module; + #endif ++ card->module = module; + INIT_LIST_HEAD(&card->devices); + init_rwsem(&card->controls_rwsem); + rwlock_init(&card->ctl_files_rwlock); +@@ -516,6 +516,14 @@ void snd_card_disconnect(struct snd_card *card) + } + } + ++#ifdef CONFIG_PM ++ /* wake up sleepers here before other callbacks for avoiding potential ++ * deadlocks with other locks (e.g. in kctls); ++ * then this notifies the shutdown and sleepers would abort immediately ++ */ ++ wake_up_all(&card->power_sleep); ++#endif ++ + /* notify all connected devices about disconnection */ + /* at this point, they cannot respond to any calls except release() */ + +@@ -543,7 +551,6 @@ void snd_card_disconnect(struct snd_card *card) + } + + #ifdef CONFIG_PM +- wake_up(&card->power_sleep); + snd_power_sync_ref(card); + #endif + } +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 4d2ee99c12a3f..d104adc75a8b0 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -544,6 +544,14 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, + SNDRV_TIMER_IFLG_START)) + return -EBUSY; + ++ /* check the actual time for the start tick; ++ * bail out as error if it's way too low (< 100us) ++ */ ++ if (start) { ++ if ((u64)snd_timer_hw_resolution(timer) * ticks < 100000) ++ return -EINVAL; ++ } ++ + if (start) + timeri->ticks = timeri->cticks = ticks; + else if (!timeri->cticks) +diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c +index 8fb688e414148..4f5e581cdd5ff 100644 +--- a/sound/pci/hda/cs35l41_hda_property.c ++++ b/sound/pci/hda/cs35l41_hda_property.c +@@ -110,8 +110,8 @@ static const struct cs35l41_config cs35l41_config_table[] = { + { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 }, + { "10433A60", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 }, + { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, +- { "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, +- { "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, ++ { "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, ++ { "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 }, + { "17AA38A9", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 }, + { "17AA38AB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 }, + { "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index b29739bd330b1..3b8b4ab488a61 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10180,8 +10180,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8c70, "HP EliteBook 835 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c71, "HP EliteBook 845 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c72, "HP EliteBook 865 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8c89, "HP ProBook 460 G11", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c8a, "HP EliteBook 630", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c8c, "HP EliteBook 660", ALC236_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8c8d, "HP ProBook 440 G11", ALC236_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8c8e, "HP ProBook 460 G11", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c90, "HP EliteBook 640", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c91, "HP EliteBook 660", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8c96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), +diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c +index d6f7f046c24e5..f634261e4f604 100644 +--- a/sound/soc/intel/avs/boards/ssm4567.c ++++ b/sound/soc/intel/avs/boards/ssm4567.c +@@ -172,7 +172,6 @@ static int avs_ssm4567_probe(struct platform_device *pdev) + card->dapm_routes = card_base_routes; + card->num_dapm_routes = ARRAY_SIZE(card_base_routes); + card->fully_routed = true; +- card->disable_route_checks = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) +diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c +index d7a9390b5e483..585579840b646 100644 +--- a/sound/soc/intel/avs/cldma.c ++++ b/sound/soc/intel/avs/cldma.c +@@ -35,7 +35,7 @@ struct hda_cldma { + + unsigned int buffer_size; + unsigned int num_periods; +- unsigned int stream_tag; ++ unsigned char stream_tag; + void __iomem *sd_addr; + + struct snd_dma_buffer dmab_data; +diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c +index d2554c8577326..284d38f3b1caf 100644 +--- a/sound/soc/intel/avs/icl.c ++++ b/sound/soc/intel/avs/icl.c +@@ -66,7 +66,7 @@ struct avs_icl_memwnd2 { + struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT]; + u8 rsvd[SZ_4K]; + }; +- u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][PAGE_SIZE]; ++ u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][SZ_4K]; + } __packed; + + #define AVS_ICL_SLOT_UNUSED \ +@@ -89,8 +89,7 @@ static int avs_icl_slot_offset(struct avs_dev *adev, union avs_icl_memwnd2_slot_ + + for (i = 0; i < AVS_ICL_MEMWND2_SLOTS_COUNT; i++) + if (desc[i].slot_id.val == slot_type.val) +- return offsetof(struct avs_icl_memwnd2, slot_array) + +- avs_skl_log_buffer_offset(adev, i); ++ return offsetof(struct avs_icl_memwnd2, slot_array) + i * SZ_4K; + return -ENXIO; + } + +diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c +index e785fc2a7008f..a44ed33b56080 100644 +--- a/sound/soc/intel/avs/path.c ++++ b/sound/soc/intel/avs/path.c +@@ -367,6 +367,7 @@ static int avs_asrc_create(struct avs_dev *adev, struct avs_path_module *mod) + struct avs_tplg_module *t = mod->template; + struct avs_asrc_cfg cfg; + ++ memset(&cfg, 0, sizeof(cfg)); + cfg.base.cpc = t->cfg_base->cpc; + cfg.base.ibs = t->cfg_base->ibs; + cfg.base.obs = t->cfg_base->obs; +diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c +index 2cafbc392cdbe..72f1bc3b7b1fe 100644 +--- a/sound/soc/intel/avs/pcm.c ++++ b/sound/soc/intel/avs/pcm.c +@@ -356,6 +356,7 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn + stream_info->sig_bits); + format_val = snd_hdac_stream_format(runtime->channels, bits, runtime->rate); + ++ snd_hdac_ext_stream_decouple(bus, link_stream, true); + snd_hdac_ext_stream_reset(link_stream); + snd_hdac_ext_stream_setup(link_stream, format_val); + +@@ -611,6 +612,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so + struct avs_dev *adev = to_avs_dev(dai->dev); + struct hdac_ext_stream *host_stream; + unsigned int format_val; ++ struct hdac_bus *bus; + unsigned int bits; + int ret; + +@@ -620,6 +622,8 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so + if (hdac_stream(host_stream)->prepared) + return 0; + ++ bus = hdac_stream(host_stream)->bus; ++ snd_hdac_ext_stream_decouple(bus, data->host_stream, true); + snd_hdac_stream_reset(hdac_stream(host_stream)); + + stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream); +diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c +index 817e543036f29..7e781a3156909 100644 +--- a/sound/soc/intel/avs/probes.c ++++ b/sound/soc/intel/avs/probes.c +@@ -19,8 +19,11 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id + struct avs_probe_cfg cfg = {{0}}; + struct avs_module_entry mentry; + u8 dummy; ++ int ret; + +- avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); ++ ret = avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); ++ if (ret) ++ return ret; + + /* + * Probe module uses no cycles, audio data format and input and output +@@ -39,11 +42,12 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id + static void avs_dsp_delete_probe(struct avs_dev *adev) + { + struct avs_module_entry mentry; ++ int ret; + +- avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); +- +- /* There is only ever one probe module instance. */ +- avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0); ++ ret = avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); ++ if (!ret) ++ /* There is only ever one probe module instance. */ ++ avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0); + } + + static inline struct hdac_ext_stream *avs_compr_get_host_stream(struct snd_compr_stream *cstream) +diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c +index 540f7a29310a9..3fe3f38c6cb69 100644 +--- a/sound/soc/intel/boards/bxt_da7219_max98357a.c ++++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c +@@ -768,6 +768,7 @@ static struct snd_soc_card broxton_audio_card = { + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = bxt_card_late_probe, + }; + +diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c +index c0eb65c14aa97..afc499be8db26 100644 +--- a/sound/soc/intel/boards/bxt_rt298.c ++++ b/sound/soc/intel/boards/bxt_rt298.c +@@ -574,6 +574,7 @@ static struct snd_soc_card broxton_rt298 = { + .dapm_routes = broxton_rt298_map, + .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = bxt_card_late_probe, + + }; +diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c +index 657e4658234ce..4098b2d32f9bc 100644 +--- a/sound/soc/intel/boards/glk_rt5682_max98357a.c ++++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c +@@ -649,6 +649,8 @@ static int geminilake_audio_probe(struct platform_device *pdev) + card = &glk_audio_card_rt5682_m98357a; + card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, ctx); ++ if (!snd_soc_acpi_sof_parent(&pdev->dev)) ++ card->disable_route_checks = true; + + /* override platform name, if required */ + mach = pdev->dev.platform_data; +diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c +index a5d8965303a88..9dbc15f9d1c9b 100644 +--- a/sound/soc/intel/boards/kbl_da7219_max98357a.c ++++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c +@@ -639,6 +639,7 @@ static struct snd_soc_card kabylake_audio_card_da7219_m98357a = { + .dapm_routes = kabylake_map, + .num_dapm_routes = ARRAY_SIZE(kabylake_map), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c +index 98c11ec0adc01..e662da5af83b5 100644 +--- a/sound/soc/intel/boards/kbl_da7219_max98927.c ++++ b/sound/soc/intel/boards/kbl_da7219_max98927.c +@@ -1036,6 +1036,7 @@ static struct snd_soc_card kbl_audio_card_da7219_m98927 = { + .codec_conf = max98927_codec_conf, + .num_configs = ARRAY_SIZE(max98927_codec_conf), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +@@ -1054,6 +1055,7 @@ static struct snd_soc_card kbl_audio_card_max98927 = { + .codec_conf = max98927_codec_conf, + .num_configs = ARRAY_SIZE(max98927_codec_conf), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +@@ -1071,6 +1073,7 @@ static struct snd_soc_card kbl_audio_card_da7219_m98373 = { + .codec_conf = max98373_codec_conf, + .num_configs = ARRAY_SIZE(max98373_codec_conf), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +@@ -1088,6 +1091,7 @@ static struct snd_soc_card kbl_audio_card_max98373 = { + .codec_conf = max98373_codec_conf, + .num_configs = ARRAY_SIZE(max98373_codec_conf), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c +index 30e0aca161cd5..894d127c482a3 100644 +--- a/sound/soc/intel/boards/kbl_rt5660.c ++++ b/sound/soc/intel/boards/kbl_rt5660.c +@@ -518,6 +518,7 @@ static struct snd_soc_card kabylake_audio_card_rt5660 = { + .dapm_routes = kabylake_rt5660_map, + .num_dapm_routes = ARRAY_SIZE(kabylake_rt5660_map), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c +index 9071b1f1cbd00..646e8ff8e9619 100644 +--- a/sound/soc/intel/boards/kbl_rt5663_max98927.c ++++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c +@@ -966,6 +966,7 @@ static struct snd_soc_card kabylake_audio_card_rt5663_m98927 = { + .codec_conf = max98927_codec_conf, + .num_configs = ARRAY_SIZE(max98927_codec_conf), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +@@ -982,6 +983,7 @@ static struct snd_soc_card kabylake_audio_card_rt5663 = { + .dapm_routes = kabylake_5663_map, + .num_dapm_routes = ARRAY_SIZE(kabylake_5663_map), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +index 178fe9c37df62..924d5d1de03ac 100644 +--- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c ++++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +@@ -791,6 +791,7 @@ static struct snd_soc_card kabylake_audio_card = { + .codec_conf = max98927_codec_conf, + .num_configs = ARRAY_SIZE(max98927_codec_conf), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = kabylake_card_late_probe, + }; + +diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c +index 6e172719c9795..4aa7fd2a05e46 100644 +--- a/sound/soc/intel/boards/skl_hda_dsp_generic.c ++++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c +@@ -227,6 +227,8 @@ static int skl_hda_audio_probe(struct platform_device *pdev) + ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; + + hda_soc_card.dev = &pdev->dev; ++ if (!snd_soc_acpi_sof_parent(&pdev->dev)) ++ hda_soc_card.disable_route_checks = true; + + if (mach->mach_params.dmic_num > 0) { + snprintf(hda_soc_components, sizeof(hda_soc_components), +diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c +index 0e7025834594a..e4630c33176e2 100644 +--- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c ++++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c +@@ -654,6 +654,7 @@ static struct snd_soc_card skylake_audio_card = { + .dapm_routes = skylake_map, + .num_dapm_routes = ARRAY_SIZE(skylake_map), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = skylake_card_late_probe, + }; + +diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c +index c59c60e280916..9a80442749081 100644 +--- a/sound/soc/intel/boards/skl_rt286.c ++++ b/sound/soc/intel/boards/skl_rt286.c +@@ -523,6 +523,7 @@ static struct snd_soc_card skylake_rt286 = { + .dapm_routes = skylake_rt286_map, + .num_dapm_routes = ARRAY_SIZE(skylake_rt286_map), + .fully_routed = true, ++ .disable_route_checks = true, + .late_probe = skylake_card_late_probe, + }; + +diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c +index dd2f806526c10..ef00792e1d49a 100644 +--- a/sound/soc/kirkwood/kirkwood-dma.c ++++ b/sound/soc/kirkwood/kirkwood-dma.c +@@ -182,6 +182,9 @@ static int kirkwood_dma_hw_params(struct snd_soc_component *component, + const struct mbus_dram_target_info *dram = mv_mbus_dram_info(); + unsigned long addr = substream->runtime->dma_addr; + ++ if (!dram) ++ return 0; ++ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + kirkwood_dma_conf_mbus_windows(priv->io, + KIRKWOOD_PLAYBACK_WIN, addr, dram); +diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c +index a58e1e3674dec..000a086a8cf44 100644 +--- a/sound/soc/mediatek/common/mtk-soundcard-driver.c ++++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c +@@ -22,7 +22,11 @@ static int set_card_codec_info(struct snd_soc_card *card, + + codec_node = of_get_child_by_name(sub_node, "codec"); + if (!codec_node) { +- dev_dbg(dev, "%s no specified codec\n", dai_link->name); ++ dev_dbg(dev, "%s no specified codec: setting dummy.\n", dai_link->name); ++ ++ dai_link->codecs = &snd_soc_dummy_dlc; ++ dai_link->num_codecs = 1; ++ dai_link->dynamic = 1; + return 0; + } + +diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c +index c1682bcdb5a66..6a39ca632f55e 100644 +--- a/sound/soc/sof/intel/hda-dai.c ++++ b/sound/soc/sof/intel/hda-dai.c +@@ -439,10 +439,17 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, + int link_id) + { + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); ++ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + const struct hda_dai_widget_dma_ops *ops; ++ struct snd_soc_dai_link_ch_map *ch_maps; + struct hdac_ext_stream *hext_stream; ++ struct snd_soc_dai *dai; + struct snd_sof_dev *sdev; ++ bool cpu_dai_found = false; ++ int cpu_dai_id; ++ int ch_mask; + int ret; ++ int j; + + ret = non_hda_dai_hw_params(substream, params, cpu_dai); + if (ret < 0) { +@@ -457,9 +464,29 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, + if (!hext_stream) + return -ENODEV; + +- /* in the case of SoundWire we need to program the PCMSyCM registers */ ++ /* ++ * in the case of SoundWire we need to program the PCMSyCM registers. In case ++ * of aggregated devices, we need to define the channel mask for each sublink ++ * by reconstructing the split done in soc-pcm.c ++ */ ++ for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) { ++ if (dai == cpu_dai) { ++ cpu_dai_found = true; ++ break; ++ } ++ } ++ ++ if (!cpu_dai_found) ++ return -ENODEV; ++ ++ ch_mask = 0; ++ for_each_link_ch_maps(rtd->dai_link, j, ch_maps) { ++ if (ch_maps->cpu == cpu_dai_id) ++ ch_mask |= ch_maps->ch_mask; ++ } ++ + ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, +- GENMASK(params_channels(params) - 1, 0), ++ ch_mask, + hdac_stream(hext_stream)->stream_tag, + substream->stream); + if (ret < 0) { +diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c +index aeb4350cce6bb..6055a33bb4bf6 100644 +--- a/sound/soc/sof/intel/lnl.c ++++ b/sound/soc/sof/intel/lnl.c +@@ -16,6 +16,7 @@ + #include "hda-ipc.h" + #include "../sof-audio.h" + #include "mtl.h" ++#include "lnl.h" + #include <sound/hda-mlink.h> + + /* LunarLake ops */ +@@ -208,7 +209,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = { + .ipc_ack = MTL_DSP_REG_HFIPCXIDA, + .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, + .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, +- .rom_status_reg = MTL_DSP_ROM_STS, ++ .rom_status_reg = LNL_DSP_REG_HFDSC, + .rom_init_timeout = 300, + .ssp_count = MTL_SSP_COUNT, + .d0i3_offset = MTL_HDA_VS_D0I3C, +diff --git a/sound/soc/sof/intel/lnl.h b/sound/soc/sof/intel/lnl.h +new file mode 100644 +index 0000000000000..4f4734fe7e089 +--- /dev/null ++++ b/sound/soc/sof/intel/lnl.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ ++/* ++ * This file is provided under a dual BSD/GPLv2 license. When using or ++ * redistributing this file, you may do so under either license. ++ * ++ * Copyright(c) 2024 Intel Corporation. All rights reserved. ++ */ ++ ++#ifndef __SOF_INTEL_LNL_H ++#define __SOF_INTEL_LNL_H ++ ++#define LNL_DSP_REG_HFDSC 0x160200 /* DSP core0 status */ ++#define LNL_DSP_REG_HFDEC 0x160204 /* DSP core0 error */ ++ ++#endif /* __SOF_INTEL_LNL_H */ +diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c +index 060c34988e90d..05023763080d9 100644 +--- a/sound/soc/sof/intel/mtl.c ++++ b/sound/soc/sof/intel/mtl.c +@@ -439,7 +439,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) + { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; +- unsigned int status; ++ unsigned int status, target_status; + u32 ipc_hdr, flags; + char *dump_msg; + int ret; +@@ -485,13 +485,40 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) + + mtl_enable_ipc_interrupts(sdev); + ++ if (chip->rom_status_reg == MTL_DSP_ROM_STS) { ++ /* ++ * Workaround: when the ROM status register is pointing to ++ * the SRAM window (MTL_DSP_ROM_STS) the platform cannot catch ++ * ROM_INIT_DONE because of a very short timing window. ++ * Follow the recommendations and skip target state waiting. ++ */ ++ return 0; ++ } ++ + /* +- * ACE workaround: don't wait for ROM INIT. +- * The platform cannot catch ROM_INIT_DONE because of a very short +- * timing window. Follow the recommendations and skip this part. ++ * step 7: ++ * - Cold/Full boot: wait for ROM init to proceed to download the firmware ++ * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR) + */ ++ if (imr_boot) ++ target_status = FSR_STATE_FW_ENTERED; ++ else ++ target_status = FSR_STATE_INIT_DONE; + +- return 0; ++ ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, ++ chip->rom_status_reg, status, ++ (FSR_TO_STATE_CODE(status) == target_status), ++ HDA_DSP_REG_POLL_INTERVAL_US, ++ chip->rom_init_timeout * ++ USEC_PER_MSEC); ++ ++ if (!ret) ++ return 0; ++ ++ if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) ++ dev_err(sdev->dev, ++ "%s: timeout with rom_status_reg (%#x) read\n", ++ __func__, chip->rom_status_reg); + + err: + flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL; +@@ -503,6 +530,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) + dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d", + hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS); + snd_sof_dsp_dbg_dump(sdev, dump_msg, flags); ++ mtl_enable_interrupts(sdev, false); + mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE); + + kfree(dump_msg); +@@ -727,7 +755,7 @@ const struct sof_intel_dsp_desc mtl_chip_info = { + .ipc_ack = MTL_DSP_REG_HFIPCXIDA, + .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, + .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, +- .rom_status_reg = MTL_DSP_ROM_STS, ++ .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY, + .rom_init_timeout = 300, + .ssp_count = MTL_SSP_COUNT, + .ssp_base_offset = CNL_SSP_BASE_OFFSET, +@@ -755,7 +783,7 @@ const struct sof_intel_dsp_desc arl_s_chip_info = { + .ipc_ack = MTL_DSP_REG_HFIPCXIDA, + .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, + .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, +- .rom_status_reg = MTL_DSP_ROM_STS, ++ .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY, + .rom_init_timeout = 300, + .ssp_count = MTL_SSP_COUNT, + .ssp_base_offset = CNL_SSP_BASE_OFFSET, +diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h +index ea8c1b83f7127..3c56427a966bf 100644 +--- a/sound/soc/sof/intel/mtl.h ++++ b/sound/soc/sof/intel/mtl.h +@@ -70,8 +70,8 @@ + #define MTL_DSP_ROM_STS MTL_SRAM_WINDOW_OFFSET(0) /* ROM status */ + #define MTL_DSP_ROM_ERROR (MTL_SRAM_WINDOW_OFFSET(0) + 0x4) /* ROM error code */ + +-#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* ROM debug status */ +-#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* ROM debug error code */ ++#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* DSP core0 status */ ++#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* DSP core0 error */ + #define MTL_DSP_REG_HfIMRIS1 0x162088 + #define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0) + +diff --git a/tools/arch/x86/lib/x86-opcode-map.txt b/tools/arch/x86/lib/x86-opcode-map.txt +index 12af572201a29..da9347552be69 100644 +--- a/tools/arch/x86/lib/x86-opcode-map.txt ++++ b/tools/arch/x86/lib/x86-opcode-map.txt +@@ -148,7 +148,7 @@ AVXcode: + 65: SEG=GS (Prefix) + 66: Operand-Size (Prefix) + 67: Address-Size (Prefix) +-68: PUSH Iz (d64) ++68: PUSH Iz + 69: IMUL Gv,Ev,Iz + 6a: PUSH Ib (d64) + 6b: IMUL Gv,Ev,Ib +@@ -698,10 +698,10 @@ AVXcode: 2 + 4d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev) + 4e: vrsqrt14ps/d Vpd,Wpd (66),(ev) + 4f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev) +-50: vpdpbusd Vx,Hx,Wx (66),(ev) +-51: vpdpbusds Vx,Hx,Wx (66),(ev) +-52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66),(ev) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev) +-53: vpdpwssds Vx,Hx,Wx (66),(ev) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev) ++50: vpdpbusd Vx,Hx,Wx (66) ++51: vpdpbusds Vx,Hx,Wx (66) ++52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev) ++53: vpdpwssds Vx,Hx,Wx (66) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev) + 54: vpopcntb/w Vx,Wx (66),(ev) + 55: vpopcntd/q Vx,Wx (66),(ev) + 58: vpbroadcastd Vx,Wx (66),(v) +diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c +index cc6e6aae2447d..958e92acca8e2 100644 +--- a/tools/bpf/bpftool/common.c ++++ b/tools/bpf/bpftool/common.c +@@ -244,29 +244,101 @@ int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type) + return fd; + } + +-int mount_bpffs_for_pin(const char *name, bool is_dir) ++int create_and_mount_bpffs_dir(const char *dir_name) + { + char err_str[ERR_MAX_LEN]; +- char *file; +- char *dir; ++ bool dir_exists; + int err = 0; + +- if (is_dir && is_bpffs(name)) ++ if (is_bpffs(dir_name)) + return err; + +- file = malloc(strlen(name) + 1); +- if (!file) { ++ dir_exists = access(dir_name, F_OK) == 0; ++ ++ if (!dir_exists) { ++ char *temp_name; ++ char *parent_name; ++ ++ temp_name = strdup(dir_name); ++ if (!temp_name) { ++ p_err("mem alloc failed"); ++ return -1; ++ } ++ ++ parent_name = dirname(temp_name); ++ ++ if (is_bpffs(parent_name)) { ++ /* nothing to do if already mounted */ ++ free(temp_name); ++ return err; ++ } ++ ++ if (access(parent_name, F_OK) == -1) { ++ p_err("can't create dir '%s' to pin BPF object: parent dir '%s' doesn't exist", ++ dir_name, parent_name); ++ free(temp_name); ++ return -1; ++ } ++ ++ free(temp_name); ++ } ++ ++ if (block_mount) { ++ p_err("no BPF file system found, not mounting it due to --nomount option"); ++ return -1; ++ } ++ ++ if (!dir_exists) { ++ err = mkdir(dir_name, S_IRWXU); ++ if (err) { ++ p_err("failed to create dir '%s': %s", dir_name, strerror(errno)); ++ return err; ++ } ++ } ++ ++ err = mnt_fs(dir_name, "bpf", err_str, ERR_MAX_LEN); ++ if (err) { ++ err_str[ERR_MAX_LEN - 1] = '\0'; ++ p_err("can't mount BPF file system on given dir '%s': %s", ++ dir_name, err_str); ++ ++ if (!dir_exists) ++ rmdir(dir_name); ++ } ++ ++ return err; ++} ++ ++int mount_bpffs_for_file(const char *file_name) ++{ ++ char err_str[ERR_MAX_LEN]; ++ char *temp_name; ++ char *dir; ++ int err = 0; ++ ++ if (access(file_name, F_OK) != -1) { ++ p_err("can't pin BPF object: path '%s' already exists", file_name); ++ return -1; ++ } ++ ++ temp_name = strdup(file_name); ++ if (!temp_name) { + p_err("mem alloc failed"); + return -1; + } + +- strcpy(file, name); +- dir = dirname(file); ++ dir = dirname(temp_name); + + if (is_bpffs(dir)) + /* nothing to do if already mounted */ + goto out_free; + ++ if (access(dir, F_OK) == -1) { ++ p_err("can't pin BPF object: dir '%s' doesn't exist", dir); ++ err = -1; ++ goto out_free; ++ } ++ + if (block_mount) { + p_err("no BPF file system found, not mounting it due to --nomount option"); + err = -1; +@@ -276,12 +348,12 @@ int mount_bpffs_for_pin(const char *name, bool is_dir) + err = mnt_fs(dir, "bpf", err_str, ERR_MAX_LEN); + if (err) { + err_str[ERR_MAX_LEN - 1] = '\0'; +- p_err("can't mount BPF file system to pin the object (%s): %s", +- name, err_str); ++ p_err("can't mount BPF file system to pin the object '%s': %s", ++ file_name, err_str); + } + + out_free: +- free(file); ++ free(temp_name); + return err; + } + +@@ -289,7 +361,7 @@ int do_pin_fd(int fd, const char *name) + { + int err; + +- err = mount_bpffs_for_pin(name, false); ++ err = mount_bpffs_for_file(name); + if (err) + return err; + +diff --git a/tools/bpf/bpftool/iter.c b/tools/bpf/bpftool/iter.c +index 6b0e5202ca7a9..5c39c2ed36a2b 100644 +--- a/tools/bpf/bpftool/iter.c ++++ b/tools/bpf/bpftool/iter.c +@@ -76,7 +76,7 @@ static int do_pin(int argc, char **argv) + goto close_obj; + } + +- err = mount_bpffs_for_pin(path, false); ++ err = mount_bpffs_for_file(path); + if (err) + goto close_link; + +diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h +index b8bb08d10dec9..9eb764fe4cc8b 100644 +--- a/tools/bpf/bpftool/main.h ++++ b/tools/bpf/bpftool/main.h +@@ -142,7 +142,8 @@ const char *get_fd_type_name(enum bpf_obj_type type); + char *get_fdinfo(int fd, const char *key); + int open_obj_pinned(const char *path, bool quiet); + int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type); +-int mount_bpffs_for_pin(const char *name, bool is_dir); ++int mount_bpffs_for_file(const char *file_name); ++int create_and_mount_bpffs_dir(const char *dir_name); + int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(int *, char ***)); + int do_pin_fd(int fd, const char *name); + +diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c +index 9cb42a3366c07..4c4cf16a40ba7 100644 +--- a/tools/bpf/bpftool/prog.c ++++ b/tools/bpf/bpftool/prog.c +@@ -1778,7 +1778,10 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) + goto err_close_obj; + } + +- err = mount_bpffs_for_pin(pinfile, !first_prog_only); ++ if (first_prog_only) ++ err = mount_bpffs_for_file(pinfile); ++ else ++ err = create_and_mount_bpffs_dir(pinfile); + if (err) + goto err_close_obj; + +diff --git a/tools/bpf/bpftool/skeleton/pid_iter.bpf.c b/tools/bpf/bpftool/skeleton/pid_iter.bpf.c +index 26004f0c5a6ae..7bdbcac3cf628 100644 +--- a/tools/bpf/bpftool/skeleton/pid_iter.bpf.c ++++ b/tools/bpf/bpftool/skeleton/pid_iter.bpf.c +@@ -102,8 +102,8 @@ int iter(struct bpf_iter__task_file *ctx) + BPF_LINK_TYPE_PERF_EVENT___local)) { + struct bpf_link *link = (struct bpf_link *) file->private_data; + +- if (link->type == bpf_core_enum_value(enum bpf_link_type___local, +- BPF_LINK_TYPE_PERF_EVENT___local)) { ++ if (BPF_CORE_READ(link, type) == bpf_core_enum_value(enum bpf_link_type___local, ++ BPF_LINK_TYPE_PERF_EVENT___local)) { + e.has_bpf_cookie = true; + e.bpf_cookie = get_bpf_cookie(link); + } +diff --git a/tools/bpf/bpftool/struct_ops.c b/tools/bpf/bpftool/struct_ops.c +index d573f2640d8e9..aa43dead249cb 100644 +--- a/tools/bpf/bpftool/struct_ops.c ++++ b/tools/bpf/bpftool/struct_ops.c +@@ -515,7 +515,7 @@ static int do_register(int argc, char **argv) + if (argc == 1) + linkdir = GET_ARG(); + +- if (linkdir && mount_bpffs_for_pin(linkdir, true)) { ++ if (linkdir && create_and_mount_bpffs_dir(linkdir)) { + p_err("can't mount bpffs for pinning"); + return -1; + } +diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h +index bacfd35c51565..5be9d3c7435a8 100644 +--- a/tools/include/nolibc/stdlib.h ++++ b/tools/include/nolibc/stdlib.h +@@ -185,7 +185,7 @@ void *realloc(void *old_ptr, size_t new_size) + if (__builtin_expect(!ret, 0)) + return NULL; + +- memcpy(ret, heap->user_p, heap->len); ++ memcpy(ret, heap->user_p, user_p_len); + munmap(heap, heap->len); + return ret; + } +diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h +index 3c42b9f1bada3..bcd84985faf48 100644 +--- a/tools/include/uapi/linux/bpf.h ++++ b/tools/include/uapi/linux/bpf.h +@@ -7150,7 +7150,7 @@ struct bpf_fib_lookup { + + /* output: MTU value */ + __u16 mtu_result; +- }; ++ } __attribute__((packed, aligned(2))); + /* input: L3 device index for lookup + * output: device index from FIB lookup + */ +diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c +index 97ec005c3c47f..145b8bd1d5ff1 100644 +--- a/tools/lib/bpf/bpf.c ++++ b/tools/lib/bpf/bpf.c +@@ -105,7 +105,7 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts) + */ + int probe_memcg_account(int token_fd) + { +- const size_t attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd); ++ const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd); + struct bpf_insn insns[] = { + BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns), + BPF_EXIT_INSN(), +diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c +index 4e783cc7fc4b5..a336786a22a38 100644 +--- a/tools/lib/bpf/features.c ++++ b/tools/lib/bpf/features.c +@@ -22,7 +22,7 @@ int probe_fd(int fd) + + static int probe_kern_prog_name(int token_fd) + { +- const size_t attr_sz = offsetofend(union bpf_attr, prog_name); ++ const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd); + struct bpf_insn insns[] = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index a2061fcd612d7..f515cf264a0a2 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -7321,9 +7321,9 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog + char *cp, errmsg[STRERR_BUFSIZE]; + size_t log_buf_size = 0; + char *log_buf = NULL, *tmp; +- int btf_fd, ret, err; + bool own_log_buf = true; + __u32 log_level = prog->log_level; ++ int ret, err; + + if (prog->type == BPF_PROG_TYPE_UNSPEC) { + /* +@@ -7347,9 +7347,8 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog + load_attr.prog_ifindex = prog->prog_ifindex; + + /* specify func_info/line_info only if kernel supports them */ +- btf_fd = btf__fd(obj->btf); +- if (btf_fd >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) { +- load_attr.prog_btf_fd = btf_fd; ++ if (obj->btf && btf__fd(obj->btf) >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) { ++ load_attr.prog_btf_fd = btf__fd(obj->btf); + load_attr.func_info = prog->func_info; + load_attr.func_info_rec_size = prog->func_info_rec_size; + load_attr.func_info_cnt = prog->func_info_cnt; +@@ -11476,7 +11475,7 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru + + n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern); + if (n < 1) { +- pr_warn("kprobe multi pattern is invalid: %s\n", pattern); ++ pr_warn("kprobe multi pattern is invalid: %s\n", spec); + return -EINVAL; + } + +diff --git a/tools/testing/selftests/bpf/cgroup_helpers.c b/tools/testing/selftests/bpf/cgroup_helpers.c +index 19be9c63d5e84..e812876d79c7e 100644 +--- a/tools/testing/selftests/bpf/cgroup_helpers.c ++++ b/tools/testing/selftests/bpf/cgroup_helpers.c +@@ -508,6 +508,9 @@ int cgroup_setup_and_join(const char *path) { + /** + * setup_classid_environment() - Setup the cgroupv1 net_cls environment + * ++ * This function should only be called in a custom mount namespace, e.g. ++ * created by running setup_cgroup_environment. ++ * + * After calling this function, cleanup_classid_environment should be called + * once testing is complete. + * +diff --git a/tools/testing/selftests/bpf/network_helpers.c b/tools/testing/selftests/bpf/network_helpers.c +index 6db27a9088e97..be96bf022316f 100644 +--- a/tools/testing/selftests/bpf/network_helpers.c ++++ b/tools/testing/selftests/bpf/network_helpers.c +@@ -461,6 +461,8 @@ struct nstoken *open_netns(const char *name) + + return token; + fail: ++ if (token->orig_netns_fd != -1) ++ close(token->orig_netns_fd); + free(token); + return NULL; + } +diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c b/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c +index 74d6d7546f40f..25332e596750f 100644 +--- a/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c ++++ b/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c +@@ -87,9 +87,12 @@ void test_cgroup1_hierarchy(void) + goto destroy; + + /* Setup cgroup1 hierarchy */ ++ err = setup_cgroup_environment(); ++ if (!ASSERT_OK(err, "setup_cgroup_environment")) ++ goto destroy; + err = setup_classid_environment(); + if (!ASSERT_OK(err, "setup_classid_environment")) +- goto destroy; ++ goto cleanup_cgroup; + + err = join_classid(); + if (!ASSERT_OK(err, "join_cgroup1")) +@@ -153,6 +156,8 @@ void test_cgroup1_hierarchy(void) + + cleanup: + cleanup_classid_environment(); ++cleanup_cgroup: ++ cleanup_cgroup_environment(); + destroy: + test_cgroup1_hierarchy__destroy(skel); + } +diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c +index 498d3bdaa4b0b..bad0ea167be70 100644 +--- a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c ++++ b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c +@@ -107,8 +107,8 @@ void test_xdp_do_redirect(void) + .attach_point = BPF_TC_INGRESS); + + memcpy(&data[sizeof(__u64)], &pkt_udp, sizeof(pkt_udp)); +- *((__u32 *)data) = 0x42; /* metadata test value */ +- *((__u32 *)data + 4) = 0; ++ ((__u32 *)data)[0] = 0x42; /* metadata test value */ ++ ((__u32 *)data)[1] = 0; + + skel = test_xdp_do_redirect__open(); + if (!ASSERT_OK_PTR(skel, "skel")) +diff --git a/tools/testing/selftests/bpf/progs/bench_local_storage_create.c b/tools/testing/selftests/bpf/progs/bench_local_storage_create.c +index e4bfbba6c1936..c8ec0d0368e4a 100644 +--- a/tools/testing/selftests/bpf/progs/bench_local_storage_create.c ++++ b/tools/testing/selftests/bpf/progs/bench_local_storage_create.c +@@ -61,14 +61,15 @@ SEC("lsm.s/socket_post_create") + int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, + int protocol, int kern) + { ++ struct sock *sk = sock->sk; + struct storage *stg; + __u32 pid; + + pid = bpf_get_current_pid_tgid() >> 32; +- if (pid != bench_pid) ++ if (pid != bench_pid || !sk) + return 0; + +- stg = bpf_sk_storage_get(&sk_storage_map, sock->sk, NULL, ++ stg = bpf_sk_storage_get(&sk_storage_map, sk, NULL, + BPF_LOCAL_STORAGE_GET_F_CREATE); + + if (stg) +diff --git a/tools/testing/selftests/bpf/progs/local_storage.c b/tools/testing/selftests/bpf/progs/local_storage.c +index e5e3a8b8dd075..637e75df2e146 100644 +--- a/tools/testing/selftests/bpf/progs/local_storage.c ++++ b/tools/testing/selftests/bpf/progs/local_storage.c +@@ -140,11 +140,12 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, + { + __u32 pid = bpf_get_current_pid_tgid() >> 32; + struct local_storage *storage; ++ struct sock *sk = sock->sk; + +- if (pid != monitored_pid) ++ if (pid != monitored_pid || !sk) + return 0; + +- storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0, 0); ++ storage = bpf_sk_storage_get(&sk_storage_map, sk, 0, 0); + if (!storage) + return 0; + +@@ -155,24 +156,24 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, + /* This tests that we can associate multiple elements + * with the local storage. + */ +- storage = bpf_sk_storage_get(&sk_storage_map2, sock->sk, 0, ++ storage = bpf_sk_storage_get(&sk_storage_map2, sk, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!storage) + return 0; + +- if (bpf_sk_storage_delete(&sk_storage_map2, sock->sk)) ++ if (bpf_sk_storage_delete(&sk_storage_map2, sk)) + return 0; + +- storage = bpf_sk_storage_get(&sk_storage_map2, sock->sk, 0, ++ storage = bpf_sk_storage_get(&sk_storage_map2, sk, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!storage) + return 0; + +- if (bpf_sk_storage_delete(&sk_storage_map, sock->sk)) ++ if (bpf_sk_storage_delete(&sk_storage_map, sk)) + return 0; + + /* Ensure that the sk_storage_map is disconnected from the storage. */ +- if (!sock->sk->sk_bpf_storage || sock->sk->sk_bpf_storage->smap) ++ if (!sk->sk_bpf_storage || sk->sk_bpf_storage->smap) + return 0; + + sk_storage_result = 0; +@@ -185,11 +186,12 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type, + { + __u32 pid = bpf_get_current_pid_tgid() >> 32; + struct local_storage *storage; ++ struct sock *sk = sock->sk; + +- if (pid != monitored_pid) ++ if (pid != monitored_pid || !sk) + return 0; + +- storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0, ++ storage = bpf_sk_storage_get(&sk_storage_map, sk, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!storage) + return 0; +diff --git a/tools/testing/selftests/bpf/progs/lsm_cgroup.c b/tools/testing/selftests/bpf/progs/lsm_cgroup.c +index 02c11d16b692a..d7598538aa2da 100644 +--- a/tools/testing/selftests/bpf/progs/lsm_cgroup.c ++++ b/tools/testing/selftests/bpf/progs/lsm_cgroup.c +@@ -103,11 +103,15 @@ static __always_inline int real_bind(struct socket *sock, + int addrlen) + { + struct sockaddr_ll sa = {}; ++ struct sock *sk = sock->sk; + +- if (sock->sk->__sk_common.skc_family != AF_PACKET) ++ if (!sk) ++ return 1; ++ ++ if (sk->__sk_common.skc_family != AF_PACKET) + return 1; + +- if (sock->sk->sk_kern_sock) ++ if (sk->sk_kern_sock) + return 1; + + bpf_probe_read_kernel(&sa, sizeof(sa), address); +diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c +index 024a0faafb3be..43612de44fbf5 100644 +--- a/tools/testing/selftests/bpf/test_sockmap.c ++++ b/tools/testing/selftests/bpf/test_sockmap.c +@@ -2104,9 +2104,9 @@ int main(int argc, char **argv) + free(options.whitelist); + if (options.blacklist) + free(options.blacklist); ++ close(cg_fd); + if (cg_created) + cleanup_cgroup_environment(); +- close(cg_fd); + return err; + } + +diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c +index 0340d4ca8f51c..432db923bced0 100644 +--- a/tools/testing/selftests/cgroup/cgroup_util.c ++++ b/tools/testing/selftests/cgroup/cgroup_util.c +@@ -195,10 +195,10 @@ int cg_write_numeric(const char *cgroup, const char *control, long value) + return cg_write(cgroup, control, buf); + } + +-int cg_find_unified_root(char *root, size_t len) ++int cg_find_unified_root(char *root, size_t len, bool *nsdelegate) + { + char buf[10 * PAGE_SIZE]; +- char *fs, *mount, *type; ++ char *fs, *mount, *type, *options; + const char delim[] = "\n\t "; + + if (read_text("/proc/self/mounts", buf, sizeof(buf)) <= 0) +@@ -211,12 +211,14 @@ int cg_find_unified_root(char *root, size_t len) + for (fs = strtok(buf, delim); fs; fs = strtok(NULL, delim)) { + mount = strtok(NULL, delim); + type = strtok(NULL, delim); +- strtok(NULL, delim); ++ options = strtok(NULL, delim); + strtok(NULL, delim); + strtok(NULL, delim); + + if (strcmp(type, "cgroup2") == 0) { + strncpy(root, mount, len); ++ if (nsdelegate) ++ *nsdelegate = !!strstr(options, "nsdelegate"); + return 0; + } + } +diff --git a/tools/testing/selftests/cgroup/cgroup_util.h b/tools/testing/selftests/cgroup/cgroup_util.h +index 1df7f202214af..89e8519fb2719 100644 +--- a/tools/testing/selftests/cgroup/cgroup_util.h ++++ b/tools/testing/selftests/cgroup/cgroup_util.h +@@ -21,7 +21,7 @@ static inline int values_close(long a, long b, int err) + return abs(a - b) <= (a + b) / 100 * err; + } + +-extern int cg_find_unified_root(char *root, size_t len); ++extern int cg_find_unified_root(char *root, size_t len, bool *nsdelegate); + extern char *cg_name(const char *root, const char *name); + extern char *cg_name_indexed(const char *root, const char *name, int index); + extern char *cg_control(const char *cgroup, const char *control); +diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c +index 80aa6b2373b96..a5672a91d273c 100644 +--- a/tools/testing/selftests/cgroup/test_core.c ++++ b/tools/testing/selftests/cgroup/test_core.c +@@ -18,6 +18,8 @@ + #include "../kselftest.h" + #include "cgroup_util.h" + ++static bool nsdelegate; ++ + static int touch_anon(char *buf, size_t size) + { + int fd; +@@ -775,6 +777,9 @@ static int test_cgcore_lesser_ns_open(const char *root) + pid_t pid; + int status; + ++ if (!nsdelegate) ++ return KSFT_SKIP; ++ + cg_test_a = cg_name(root, "cg_test_a"); + cg_test_b = cg_name(root, "cg_test_b"); + +@@ -862,7 +867,7 @@ int main(int argc, char *argv[]) + char root[PATH_MAX]; + int i, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), &nsdelegate)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + + if (cg_read_strstr(root, "cgroup.subtree_control", "memory")) +diff --git a/tools/testing/selftests/cgroup/test_cpu.c b/tools/testing/selftests/cgroup/test_cpu.c +index 24020a2c68dcd..186bf96f6a284 100644 +--- a/tools/testing/selftests/cgroup/test_cpu.c ++++ b/tools/testing/selftests/cgroup/test_cpu.c +@@ -700,7 +700,7 @@ int main(int argc, char *argv[]) + char root[PATH_MAX]; + int i, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + + if (cg_read_strstr(root, "cgroup.subtree_control", "cpu")) +diff --git a/tools/testing/selftests/cgroup/test_cpuset.c b/tools/testing/selftests/cgroup/test_cpuset.c +index b061ed1e05b4d..4034d14ba69ac 100644 +--- a/tools/testing/selftests/cgroup/test_cpuset.c ++++ b/tools/testing/selftests/cgroup/test_cpuset.c +@@ -249,7 +249,7 @@ int main(int argc, char *argv[]) + char root[PATH_MAX]; + int i, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + + if (cg_read_strstr(root, "cgroup.subtree_control", "cpuset")) +diff --git a/tools/testing/selftests/cgroup/test_freezer.c b/tools/testing/selftests/cgroup/test_freezer.c +index 8845353aca53b..8730645d363a7 100644 +--- a/tools/testing/selftests/cgroup/test_freezer.c ++++ b/tools/testing/selftests/cgroup/test_freezer.c +@@ -827,7 +827,7 @@ int main(int argc, char *argv[]) + char root[PATH_MAX]; + int i, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + for (i = 0; i < ARRAY_SIZE(tests); i++) { + switch (tests[i].fn(root)) { +diff --git a/tools/testing/selftests/cgroup/test_hugetlb_memcg.c b/tools/testing/selftests/cgroup/test_hugetlb_memcg.c +index f0fefeb4cc24c..856f9508ea562 100644 +--- a/tools/testing/selftests/cgroup/test_hugetlb_memcg.c ++++ b/tools/testing/selftests/cgroup/test_hugetlb_memcg.c +@@ -214,7 +214,7 @@ int main(int argc, char **argv) + return ret; + } + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + + switch (test_hugetlb_memcg(root)) { +diff --git a/tools/testing/selftests/cgroup/test_kill.c b/tools/testing/selftests/cgroup/test_kill.c +index 6153690319c9c..0e5bb6c7307a5 100644 +--- a/tools/testing/selftests/cgroup/test_kill.c ++++ b/tools/testing/selftests/cgroup/test_kill.c +@@ -276,7 +276,7 @@ int main(int argc, char *argv[]) + char root[PATH_MAX]; + int i, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + for (i = 0; i < ARRAY_SIZE(tests); i++) { + switch (tests[i].fn(root)) { +diff --git a/tools/testing/selftests/cgroup/test_kmem.c b/tools/testing/selftests/cgroup/test_kmem.c +index c82f974b85c94..137506db03127 100644 +--- a/tools/testing/selftests/cgroup/test_kmem.c ++++ b/tools/testing/selftests/cgroup/test_kmem.c +@@ -420,7 +420,7 @@ int main(int argc, char **argv) + char root[PATH_MAX]; + int i, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + + /* +diff --git a/tools/testing/selftests/cgroup/test_memcontrol.c b/tools/testing/selftests/cgroup/test_memcontrol.c +index c7c9572003a8c..b462416b38061 100644 +--- a/tools/testing/selftests/cgroup/test_memcontrol.c ++++ b/tools/testing/selftests/cgroup/test_memcontrol.c +@@ -1314,7 +1314,7 @@ int main(int argc, char **argv) + char root[PATH_MAX]; + int i, proc_status, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + + /* +diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c +index f0e488ed90d89..ef7f395453173 100644 +--- a/tools/testing/selftests/cgroup/test_zswap.c ++++ b/tools/testing/selftests/cgroup/test_zswap.c +@@ -440,7 +440,7 @@ int main(int argc, char **argv) + char root[PATH_MAX]; + int i, ret = EXIT_SUCCESS; + +- if (cg_find_unified_root(root, sizeof(root))) ++ if (cg_find_unified_root(root, sizeof(root), NULL)) + ksft_exit_skip("cgroup v2 isn't mounted\n"); + + if (!zswap_configured()) +diff --git a/tools/testing/selftests/damon/_damon_sysfs.py b/tools/testing/selftests/damon/_damon_sysfs.py +index d23d7398a27a8..fe77d7e73a25b 100644 +--- a/tools/testing/selftests/damon/_damon_sysfs.py ++++ b/tools/testing/selftests/damon/_damon_sysfs.py +@@ -287,6 +287,8 @@ class DamonCtx: + nr_schemes_file = os.path.join( + self.sysfs_dir(), 'schemes', 'nr_schemes') + content, err = read_file(nr_schemes_file) ++ if err is not None: ++ return err + if int(content) != len(self.schemes): + err = write_file(nr_schemes_file, '%d' % len(self.schemes)) + if err != None: +diff --git a/tools/testing/selftests/filesystems/binderfs/Makefile b/tools/testing/selftests/filesystems/binderfs/Makefile +index c2f7cef919c04..eb4c3b4119348 100644 +--- a/tools/testing/selftests/filesystems/binderfs/Makefile ++++ b/tools/testing/selftests/filesystems/binderfs/Makefile +@@ -3,6 +3,4 @@ + CFLAGS += $(KHDR_INCLUDES) -pthread + TEST_GEN_PROGS := binderfs_test + +-binderfs_test: binderfs_test.c ../../kselftest.h ../../kselftest_harness.h +- + include ../../lib.mk +diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc +index b9c21a81d2481..c0cdad4c400e8 100644 +--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc ++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc +@@ -53,7 +53,7 @@ fi + + echo > dynamic_events + +-if [ "$FIELDS" ] ; then ++if [ "$FIELDS" -a "$FPROBES" ] ; then + echo "t:tpevent ${TP2} obj_size=s->object_size" >> dynamic_events + echo "f:fpevent ${TP3}%return path=\$retval->name:string" >> dynamic_events + echo "t:tpevent2 ${TP4} p->se.group_node.next->prev" >> dynamic_events +diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_entry_arg.tc b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_entry_arg.tc +index d183b8a8ecf82..1e251ce2998ea 100644 +--- a/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_entry_arg.tc ++++ b/tools/testing/selftests/ftrace/test.d/dynevent/fprobe_entry_arg.tc +@@ -11,7 +11,7 @@ echo 1 > events/tests/enable + echo > trace + cat trace > /dev/null + +-function streq() { ++streq() { + test $1 = $2 + } + +diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_entry_arg.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_entry_arg.tc +index 53b82f36a1d01..e50470b531648 100644 +--- a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_entry_arg.tc ++++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_entry_arg.tc +@@ -11,7 +11,7 @@ echo 1 > events/kprobes/enable + echo > trace + cat trace > /dev/null + +-function streq() { ++streq() { + test $1 = $2 + } + +diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c +index 25110c7c0b3ed..d7a8e321bb16b 100644 +--- a/tools/testing/selftests/kcmp/kcmp_test.c ++++ b/tools/testing/selftests/kcmp/kcmp_test.c +@@ -91,7 +91,7 @@ int main(int argc, char **argv) + ksft_print_header(); + ksft_set_plan(3); + +- fd2 = open(kpath, O_RDWR, 0644); ++ fd2 = open(kpath, O_RDWR); + if (fd2 < 0) { + perror("Can't open file"); + ksft_exit_fail(); +diff --git a/tools/testing/selftests/kselftest/ktap_helpers.sh b/tools/testing/selftests/kselftest/ktap_helpers.sh +index f2fbb914e058d..79a125eb24c2e 100644 +--- a/tools/testing/selftests/kselftest/ktap_helpers.sh ++++ b/tools/testing/selftests/kselftest/ktap_helpers.sh +@@ -43,7 +43,7 @@ __ktap_test() { + directive="$3" # optional + + local directive_str= +- [[ ! -z "$directive" ]] && directive_str="# $directive" ++ [ ! -z "$directive" ] && directive_str="# $directive" + + echo $result $KTAP_TESTNO $description $directive_str + +@@ -99,7 +99,7 @@ ktap_exit_fail_msg() { + ktap_finished() { + ktap_print_totals + +- if [ $(("$KTAP_CNT_PASS" + "$KTAP_CNT_SKIP")) -eq "$KSFT_NUM_TESTS" ]; then ++ if [ $((KTAP_CNT_PASS + KTAP_CNT_SKIP)) -eq "$KSFT_NUM_TESTS" ]; then + exit "$KSFT_PASS" + else + exit "$KSFT_FAIL" +diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk +index da2cade3bab0e..8ae203d8ed7fa 100644 +--- a/tools/testing/selftests/lib.mk ++++ b/tools/testing/selftests/lib.mk +@@ -7,6 +7,8 @@ else ifneq ($(filter -%,$(LLVM)),) + LLVM_SUFFIX := $(LLVM) + endif + ++CLANG := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) ++ + CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi + CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu + CLANG_TARGET_FLAGS_hexagon := hexagon-linux-musl +@@ -18,7 +20,13 @@ CLANG_TARGET_FLAGS_riscv := riscv64-linux-gnu + CLANG_TARGET_FLAGS_s390 := s390x-linux-gnu + CLANG_TARGET_FLAGS_x86 := x86_64-linux-gnu + CLANG_TARGET_FLAGS_x86_64 := x86_64-linux-gnu +-CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH)) ++ ++# Default to host architecture if ARCH is not explicitly given. ++ifeq ($(ARCH),) ++CLANG_TARGET_FLAGS := $(shell $(CLANG) -print-target-triple) ++else ++CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH)) ++endif + + ifeq ($(CROSS_COMPILE),) + ifeq ($(CLANG_TARGET_FLAGS),) +@@ -30,7 +38,7 @@ else + CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%)) + endif # CROSS_COMPILE + +-CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) $(CLANG_FLAGS) -fintegrated-as ++CC := $(CLANG) $(CLANG_FLAGS) -fintegrated-as + else + CC := $(CROSS_COMPILE)gcc + endif # LLVM +diff --git a/tools/testing/selftests/net/amt.sh b/tools/testing/selftests/net/amt.sh +index 75528788cb95e..5175a42cbe8a2 100755 +--- a/tools/testing/selftests/net/amt.sh ++++ b/tools/testing/selftests/net/amt.sh +@@ -210,8 +210,8 @@ check_features() + + test_ipv4_forward() + { +- RESULT4=$(ip netns exec "${LISTENER}" nc -w 1 -l -u 239.0.0.1 4000) +- if [ "$RESULT4" == "172.17.0.2" ]; then ++ RESULT4=$(ip netns exec "${LISTENER}" timeout 15 socat - UDP4-LISTEN:4000,readbytes=128 || true) ++ if echo "$RESULT4" | grep -q "172.17.0.2"; then + printf "TEST: %-60s [ OK ]\n" "IPv4 amt multicast forwarding" + exit 0 + else +@@ -222,8 +222,8 @@ test_ipv4_forward() + + test_ipv6_forward() + { +- RESULT6=$(ip netns exec "${LISTENER}" nc -w 1 -l -u ff0e::5:6 6000) +- if [ "$RESULT6" == "2001:db8:3::2" ]; then ++ RESULT6=$(ip netns exec "${LISTENER}" timeout 15 socat - UDP6-LISTEN:6000,readbytes=128 || true) ++ if echo "$RESULT6" | grep -q "2001:db8:3::2"; then + printf "TEST: %-60s [ OK ]\n" "IPv6 amt multicast forwarding" + exit 0 + else +@@ -236,14 +236,14 @@ send_mcast4() + { + sleep 2 + ip netns exec "${SOURCE}" bash -c \ +- 'echo 172.17.0.2 | nc -w 1 -u 239.0.0.1 4000' & ++ 'printf "%s %128s" 172.17.0.2 | nc -w 1 -u 239.0.0.1 4000' & + } + + send_mcast6() + { + sleep 2 + ip netns exec "${SOURCE}" bash -c \ +- 'echo 2001:db8:3::2 | nc -w 1 -u ff0e::5:6 6000' & ++ 'printf "%s %128s" 2001:db8:3::2 | nc -w 1 -u ff0e::5:6 6000' & + } + + check_features +diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config +index 5e4390cac17ed..04de7a6ba6f31 100644 +--- a/tools/testing/selftests/net/config ++++ b/tools/testing/selftests/net/config +@@ -30,6 +30,7 @@ CONFIG_IP_GRE=m + CONFIG_NETFILTER=y + CONFIG_NETFILTER_ADVANCED=y + CONFIG_NF_CONNTRACK=m ++CONFIG_IPV6_MROUTE=y + CONFIG_IPV6_SIT=y + CONFIG_IP_DCCP=m + CONFIG_NF_NAT=m +diff --git a/tools/testing/selftests/net/forwarding/bridge_igmp.sh b/tools/testing/selftests/net/forwarding/bridge_igmp.sh +index 2aa66d2a1702b..e6a3e04fd83f3 100755 +--- a/tools/testing/selftests/net/forwarding/bridge_igmp.sh ++++ b/tools/testing/selftests/net/forwarding/bridge_igmp.sh +@@ -478,10 +478,10 @@ v3exc_timeout_test() + RET=0 + local X=("192.0.2.20" "192.0.2.30") + +- # GMI should be 3 seconds ++ # GMI should be 5 seconds + ip link set dev br0 type bridge mcast_query_interval 100 \ + mcast_query_response_interval 100 \ +- mcast_membership_interval 300 ++ mcast_membership_interval 500 + + v3exclude_prepare $h1 $ALL_MAC $ALL_GROUP + ip link set dev br0 type bridge mcast_query_interval 500 \ +@@ -489,7 +489,7 @@ v3exc_timeout_test() + mcast_membership_interval 1500 + + $MZ $h1 -c 1 -b $ALL_MAC -B $ALL_GROUP -t ip "proto=2,p=$MZPKT_ALLOW2" -q +- sleep 3 ++ sleep 5 + bridge -j -d -s mdb show dev br0 \ + | jq -e ".[].mdb[] | \ + select(.grp == \"$TEST_GROUP\" and \ +diff --git a/tools/testing/selftests/net/forwarding/bridge_mld.sh b/tools/testing/selftests/net/forwarding/bridge_mld.sh +index e2b9ff773c6b6..f84ab2e657547 100755 +--- a/tools/testing/selftests/net/forwarding/bridge_mld.sh ++++ b/tools/testing/selftests/net/forwarding/bridge_mld.sh +@@ -478,10 +478,10 @@ mldv2exc_timeout_test() + RET=0 + local X=("2001:db8:1::20" "2001:db8:1::30") + +- # GMI should be 3 seconds ++ # GMI should be 5 seconds + ip link set dev br0 type bridge mcast_query_interval 100 \ + mcast_query_response_interval 100 \ +- mcast_membership_interval 300 ++ mcast_membership_interval 500 + + mldv2exclude_prepare $h1 + ip link set dev br0 type bridge mcast_query_interval 500 \ +@@ -489,7 +489,7 @@ mldv2exc_timeout_test() + mcast_membership_interval 1500 + + $MZ $h1 -c 1 $MZPKT_ALLOW2 -q +- sleep 3 ++ sleep 5 + bridge -j -d -s mdb show dev br0 \ + | jq -e ".[].mdb[] | \ + select(.grp == \"$TEST_GROUP\" and \ +diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh +index f9fe182dfbd44..56a9454b7ba35 100644 +--- a/tools/testing/selftests/net/lib.sh ++++ b/tools/testing/selftests/net/lib.sh +@@ -73,15 +73,17 @@ setup_ns() + local ns="" + local ns_name="" + local ns_list="" ++ local ns_exist= + for ns_name in "$@"; do + # Some test may setup/remove same netns multi times + if unset ${ns_name} 2> /dev/null; then + ns="${ns_name,,}-$(mktemp -u XXXXXX)" + eval readonly ${ns_name}="$ns" ++ ns_exist=false + else + eval ns='$'${ns_name} + cleanup_ns "$ns" +- ++ ns_exist=true + fi + + if ! ip netns add "$ns"; then +@@ -90,7 +92,7 @@ setup_ns() + return $ksft_skip + fi + ip -n "$ns" link set lo up +- ns_list="$ns_list $ns" ++ ! $ns_exist && ns_list="$ns_list $ns" + done + NS_LIST="$NS_LIST $ns_list" + } +diff --git a/tools/testing/selftests/power_supply/test_power_supply_properties.sh b/tools/testing/selftests/power_supply/test_power_supply_properties.sh +index df272dfe1d2a9..a66b1313ed882 100755 +--- a/tools/testing/selftests/power_supply/test_power_supply_properties.sh ++++ b/tools/testing/selftests/power_supply/test_power_supply_properties.sh +@@ -23,7 +23,7 @@ count_tests() { + total_tests=0 + + for i in $SUPPLIES; do +- total_tests=$(("$total_tests" + "$NUM_TESTS")) ++ total_tests=$((total_tests + NUM_TESTS)) + done + + echo "$total_tests" +diff --git a/tools/testing/selftests/resctrl/Makefile b/tools/testing/selftests/resctrl/Makefile +index 2deac2031de9e..021863f86053a 100644 +--- a/tools/testing/selftests/resctrl/Makefile ++++ b/tools/testing/selftests/resctrl/Makefile +@@ -5,6 +5,8 @@ CFLAGS += $(KHDR_INCLUDES) + + TEST_GEN_PROGS := resctrl_tests + ++LOCAL_HDRS += $(wildcard *.h) ++ + include ../lib.mk + +-$(OUTPUT)/resctrl_tests: $(wildcard *.[ch]) ++$(OUTPUT)/resctrl_tests: $(wildcard *.c) +diff --git a/tools/tracing/latency/latency-collector.c b/tools/tracing/latency/latency-collector.c +index 0fd9c747d396d..cf263fe9deaf4 100644 +--- a/tools/tracing/latency/latency-collector.c ++++ b/tools/tracing/latency/latency-collector.c +@@ -935,12 +935,12 @@ static void show_available(void) + } + + if (!tracers) { +- warnx(no_tracer_msg); ++ warnx("%s", no_tracer_msg); + return; + } + + if (!found) { +- warnx(no_latency_tr_msg); ++ warnx("%s", no_latency_tr_msg); + tracefs_list_free(tracers); + return; + } +@@ -983,7 +983,7 @@ static const char *find_default_tracer(void) + for (i = 0; relevant_tracers[i]; i++) { + valid = tracer_valid(relevant_tracers[i], ¬racer); + if (notracer) +- errx(EXIT_FAILURE, no_tracer_msg); ++ errx(EXIT_FAILURE, "%s", no_tracer_msg); + if (valid) + return relevant_tracers[i]; + } +@@ -1878,7 +1878,7 @@ static void scan_arguments(int argc, char *argv[]) + } + valid = tracer_valid(current_tracer, ¬racer); + if (notracer) +- errx(EXIT_FAILURE, no_tracer_msg); ++ errx(EXIT_FAILURE, "%s", no_tracer_msg); + if (!valid) + errx(EXIT_FAILURE, + "The tracer %s is not supported by your kernel!\n", current_tracer); diff --git a/1003_linux-6.9.4.patch b/1003_linux-6.9.4.patch new file mode 100644 index 00000000..3470f007 --- /dev/null +++ b/1003_linux-6.9.4.patch @@ -0,0 +1,15797 @@ +diff --git a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml +index b6a7cb32f61e5..835b6db00c279 100644 +--- a/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml ++++ b/Documentation/devicetree/bindings/pci/rcar-pci-host.yaml +@@ -77,6 +77,9 @@ properties: + vpcie12v-supply: + description: The 12v regulator to use for PCIe. + ++ iommu-map: true ++ iommu-map-mask: true ++ + required: + - compatible + - reg +diff --git a/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml b/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml +index 531008f0b6ac3..002b728cbc718 100644 +--- a/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/rockchip,rk3399-pcie.yaml +@@ -37,6 +37,7 @@ properties: + description: This property is needed if using 24MHz OSC for RC's PHY. + + ep-gpios: ++ maxItems: 1 + description: pre-reset GPIO + + vpcie12v-supply: +diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +index ba966a78a1283..7543456862b80 100644 +--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml ++++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml +@@ -198,7 +198,6 @@ allOf: + enum: + - qcom,sm8550-qmp-gen4x2-pcie-phy + - qcom,sm8650-qmp-gen4x2-pcie-phy +- - qcom,x1e80100-qmp-gen3x2-pcie-phy + - qcom,x1e80100-qmp-gen4x2-pcie-phy + then: + properties: +diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml +index 91a6cc38ff7ff..c4c4fb38c51a9 100644 +--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml ++++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-ufs-phy.yaml +@@ -71,7 +71,6 @@ required: + - reg + - clocks + - clock-names +- - power-domains + - resets + - reset-names + - vdda-phy-supply +@@ -127,6 +126,21 @@ allOf: + - const: ref + - const: qref + ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - qcom,msm8996-qmp-ufs-phy ++ - qcom,msm8998-qmp-ufs-phy ++ then: ++ properties: ++ power-domains: ++ false ++ else: ++ required: ++ - power-domains ++ + additionalProperties: false + + examples: +diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml +index 0f200e3f97a9a..fce7f8a19e9c0 100644 +--- a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml ++++ b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml +@@ -15,9 +15,6 @@ description: | + properties: + compatible: + oneOf: +- - enum: +- - qcom,sc8180x-usb-hs-phy +- - qcom,usb-snps-femto-v2-phy + - items: + - enum: + - qcom,sa8775p-usb-hs-phy +@@ -26,6 +23,7 @@ properties: + - items: + - enum: + - qcom,sc7280-usb-hs-phy ++ - qcom,sc8180x-usb-hs-phy + - qcom,sdx55-usb-hs-phy + - qcom,sdx65-usb-hs-phy + - qcom,sm6375-usb-hs-phy +diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml +index bd72a326e6e06..60f30a59f3853 100644 +--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml ++++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml +@@ -97,7 +97,8 @@ patternProperties: + then: + properties: + groups: +- enum: [emmc, emmc_rst] ++ items: ++ enum: [emmc, emmc_rst] + - if: + properties: + function: +@@ -105,8 +106,9 @@ patternProperties: + then: + properties: + groups: +- enum: [esw, esw_p0_p1, esw_p2_p3_p4, rgmii_via_esw, +- rgmii_via_gmac1, rgmii_via_gmac2, mdc_mdio] ++ items: ++ enum: [esw, esw_p0_p1, esw_p2_p3_p4, rgmii_via_esw, ++ rgmii_via_gmac1, rgmii_via_gmac2, mdc_mdio] + - if: + properties: + function: +@@ -123,10 +125,11 @@ patternProperties: + then: + properties: + groups: +- enum: [i2s_in_mclk_bclk_ws, i2s1_in_data, i2s2_in_data, +- i2s3_in_data, i2s4_in_data, i2s_out_mclk_bclk_ws, +- i2s1_out_data, i2s2_out_data, i2s3_out_data, +- i2s4_out_data] ++ items: ++ enum: [i2s_in_mclk_bclk_ws, i2s1_in_data, i2s2_in_data, ++ i2s3_in_data, i2s4_in_data, i2s_out_mclk_bclk_ws, ++ i2s1_out_data, i2s2_out_data, i2s3_out_data, ++ i2s4_out_data] + - if: + properties: + function: +@@ -159,10 +162,11 @@ patternProperties: + then: + properties: + groups: +- enum: [pcie0_0_waken, pcie0_1_waken, pcie1_0_waken, +- pcie0_0_clkreq, pcie0_1_clkreq, pcie1_0_clkreq, +- pcie0_pad_perst, pcie1_pad_perst, pcie_pereset, +- pcie_wake, pcie_clkreq] ++ items: ++ enum: [pcie0_0_waken, pcie0_1_waken, pcie1_0_waken, ++ pcie0_0_clkreq, pcie0_1_clkreq, pcie1_0_clkreq, ++ pcie0_pad_perst, pcie1_pad_perst, pcie_pereset, ++ pcie_wake, pcie_clkreq] + - if: + properties: + function: +@@ -178,11 +182,12 @@ patternProperties: + then: + properties: + groups: +- enum: [pwm_ch1_0, pwm_ch1_1, pwm_ch1_2, pwm_ch2_0, pwm_ch2_1, +- pwm_ch2_2, pwm_ch3_0, pwm_ch3_1, pwm_ch3_2, pwm_ch4_0, +- pwm_ch4_1, pwm_ch4_2, pwm_ch4_3, pwm_ch5_0, pwm_ch5_1, +- pwm_ch5_2, pwm_ch6_0, pwm_ch6_1, pwm_ch6_2, pwm_ch6_3, +- pwm_ch7_0, pwm_0, pwm_1] ++ items: ++ enum: [pwm_ch1_0, pwm_ch1_1, pwm_ch1_2, pwm_ch2_0, pwm_ch2_1, ++ pwm_ch2_2, pwm_ch3_0, pwm_ch3_1, pwm_ch3_2, pwm_ch4_0, ++ pwm_ch4_1, pwm_ch4_2, pwm_ch4_3, pwm_ch5_0, pwm_ch5_1, ++ pwm_ch5_2, pwm_ch6_0, pwm_ch6_1, pwm_ch6_2, pwm_ch6_3, ++ pwm_ch7_0, pwm_0, pwm_1] + - if: + properties: + function: +@@ -260,33 +265,34 @@ patternProperties: + pins: + description: + An array of strings. Each string contains the name of a pin. +- enum: [GPIO_A, I2S1_IN, I2S1_OUT, I2S_BCLK, I2S_WS, I2S_MCLK, TXD0, +- RXD0, SPI_WP, SPI_HOLD, SPI_CLK, SPI_MOSI, SPI_MISO, SPI_CS, +- I2C_SDA, I2C_SCL, I2S2_IN, I2S3_IN, I2S4_IN, I2S2_OUT, +- I2S3_OUT, I2S4_OUT, GPIO_B, MDC, MDIO, G2_TXD0, G2_TXD1, +- G2_TXD2, G2_TXD3, G2_TXEN, G2_TXC, G2_RXD0, G2_RXD1, G2_RXD2, +- G2_RXD3, G2_RXDV, G2_RXC, NCEB, NWEB, NREB, NDL4, NDL5, NDL6, +- NDL7, NRB, NCLE, NALE, NDL0, NDL1, NDL2, NDL3, MDI_TP_P0, +- MDI_TN_P0, MDI_RP_P0, MDI_RN_P0, MDI_TP_P1, MDI_TN_P1, +- MDI_RP_P1, MDI_RN_P1, MDI_RP_P2, MDI_RN_P2, MDI_TP_P2, +- MDI_TN_P2, MDI_TP_P3, MDI_TN_P3, MDI_RP_P3, MDI_RN_P3, +- MDI_RP_P4, MDI_RN_P4, MDI_TP_P4, MDI_TN_P4, PMIC_SCL, +- PMIC_SDA, SPIC1_CLK, SPIC1_MOSI, SPIC1_MISO, SPIC1_CS, +- GPIO_D, WATCHDOG, RTS3_N, CTS3_N, TXD3, RXD3, PERST0_N, +- PERST1_N, WLED_N, EPHY_LED0_N, AUXIN0, AUXIN1, AUXIN2, +- AUXIN3, TXD4, RXD4, RTS4_N, CST4_N, PWM1, PWM2, PWM3, PWM4, +- PWM5, PWM6, PWM7, GPIO_E, TOP_5G_CLK, TOP_5G_DATA, +- WF0_5G_HB0, WF0_5G_HB1, WF0_5G_HB2, WF0_5G_HB3, WF0_5G_HB4, +- WF0_5G_HB5, WF0_5G_HB6, XO_REQ, TOP_RST_N, SYS_WATCHDOG, +- EPHY_LED0_N_JTDO, EPHY_LED1_N_JTDI, EPHY_LED2_N_JTMS, +- EPHY_LED3_N_JTCLK, EPHY_LED4_N_JTRST_N, WF2G_LED_N, +- WF5G_LED_N, GPIO_9, GPIO_10, GPIO_11, GPIO_12, UART1_TXD, +- UART1_RXD, UART1_CTS, UART1_RTS, UART2_TXD, UART2_RXD, +- UART2_CTS, UART2_RTS, SMI_MDC, SMI_MDIO, PCIE_PERESET_N, +- PWM_0, GPIO_0, GPIO_1, GPIO_2, GPIO_3, GPIO_4, GPIO_5, +- GPIO_6, GPIO_7, GPIO_8, UART0_TXD, UART0_RXD, TOP_2G_CLK, +- TOP_2G_DATA, WF0_2G_HB0, WF0_2G_HB1, WF0_2G_HB2, WF0_2G_HB3, +- WF0_2G_HB4, WF0_2G_HB5, WF0_2G_HB6] ++ items: ++ enum: [GPIO_A, I2S1_IN, I2S1_OUT, I2S_BCLK, I2S_WS, I2S_MCLK, TXD0, ++ RXD0, SPI_WP, SPI_HOLD, SPI_CLK, SPI_MOSI, SPI_MISO, SPI_CS, ++ I2C_SDA, I2C_SCL, I2S2_IN, I2S3_IN, I2S4_IN, I2S2_OUT, ++ I2S3_OUT, I2S4_OUT, GPIO_B, MDC, MDIO, G2_TXD0, G2_TXD1, ++ G2_TXD2, G2_TXD3, G2_TXEN, G2_TXC, G2_RXD0, G2_RXD1, G2_RXD2, ++ G2_RXD3, G2_RXDV, G2_RXC, NCEB, NWEB, NREB, NDL4, NDL5, NDL6, ++ NDL7, NRB, NCLE, NALE, NDL0, NDL1, NDL2, NDL3, MDI_TP_P0, ++ MDI_TN_P0, MDI_RP_P0, MDI_RN_P0, MDI_TP_P1, MDI_TN_P1, ++ MDI_RP_P1, MDI_RN_P1, MDI_RP_P2, MDI_RN_P2, MDI_TP_P2, ++ MDI_TN_P2, MDI_TP_P3, MDI_TN_P3, MDI_RP_P3, MDI_RN_P3, ++ MDI_RP_P4, MDI_RN_P4, MDI_TP_P4, MDI_TN_P4, PMIC_SCL, ++ PMIC_SDA, SPIC1_CLK, SPIC1_MOSI, SPIC1_MISO, SPIC1_CS, ++ GPIO_D, WATCHDOG, RTS3_N, CTS3_N, TXD3, RXD3, PERST0_N, ++ PERST1_N, WLED_N, EPHY_LED0_N, AUXIN0, AUXIN1, AUXIN2, ++ AUXIN3, TXD4, RXD4, RTS4_N, CST4_N, PWM1, PWM2, PWM3, PWM4, ++ PWM5, PWM6, PWM7, GPIO_E, TOP_5G_CLK, TOP_5G_DATA, ++ WF0_5G_HB0, WF0_5G_HB1, WF0_5G_HB2, WF0_5G_HB3, WF0_5G_HB4, ++ WF0_5G_HB5, WF0_5G_HB6, XO_REQ, TOP_RST_N, SYS_WATCHDOG, ++ EPHY_LED0_N_JTDO, EPHY_LED1_N_JTDI, EPHY_LED2_N_JTMS, ++ EPHY_LED3_N_JTCLK, EPHY_LED4_N_JTRST_N, WF2G_LED_N, ++ WF5G_LED_N, GPIO_9, GPIO_10, GPIO_11, GPIO_12, UART1_TXD, ++ UART1_RXD, UART1_CTS, UART1_RTS, UART2_TXD, UART2_RXD, ++ UART2_CTS, UART2_RTS, SMI_MDC, SMI_MDIO, PCIE_PERESET_N, ++ PWM_0, GPIO_0, GPIO_1, GPIO_2, GPIO_3, GPIO_4, GPIO_5, ++ GPIO_6, GPIO_7, GPIO_8, UART0_TXD, UART0_RXD, TOP_2G_CLK, ++ TOP_2G_DATA, WF0_2G_HB0, WF0_2G_HB1, WF0_2G_HB2, WF0_2G_HB3, ++ WF0_2G_HB4, WF0_2G_HB5, WF0_2G_HB6] + + bias-disable: true + +diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm4450-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm4450-tlmm.yaml +index bb675c8ec220f..1b941b276b3f8 100644 +--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm4450-tlmm.yaml ++++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm4450-tlmm.yaml +@@ -72,40 +72,24 @@ $defs: + description: + Specify the alternative function to be configured for the specified + pins. +- enum: [ gpio, atest_char, atest_char0, atest_char1, atest_char2, +- atest_char3, atest_usb0, atest_usb00, atest_usb01, atest_usb02, +- atest_usb03, audio_ref, cam_mclk, cci_async, cci_i2c, +- cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, +- cmu_rng0, cmu_rng1, cmu_rng2, cmu_rng3, coex_uart1, cri_trng, +- cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0, ddr_pxi1, +- dp0_hot, gcc_gp1, gcc_gp2, gcc_gp3, host2wlan_sol, ibi_i3c, +- jitter_bist, mdp_vsync, mdp_vsync0, mdp_vsync1, mdp_vsync2, +- mdp_vsync3, mi2s0_data0, mi2s0_data1, mi2s0_sck, mi2s0_ws, +- mi2s2_data0, mi2s2_data1, mi2s2_sck, mi2s2_ws, mi2s_mclk0, +- mi2s_mclk1, nav_gpio0, nav_gpio1, nav_gpio2, pcie0_clk, +- phase_flag0, phase_flag1, phase_flag10, phase_flag11, +- phase_flag12, phase_flag13, phase_flag14, phase_flag15, +- phase_flag16, phase_flag17, phase_flag18, phase_flag19, +- phase_flag2, phase_flag20, phase_flag21, phase_flag22, +- phase_flag23, phase_flag24, phase_flag25, phase_flag26, +- phase_flag27, phase_flag28, phase_flag29, phase_flag3, +- phase_flag30, phase_flag31, phase_flag4, phase_flag5, +- phase_flag6, phase_flag7, phase_flag8, phase_flag9, +- pll_bist, pll_clk, prng_rosc0, prng_rosc1, prng_rosc2, +- prng_rosc3, qdss_cti, qdss_gpio, qdss_gpio0, qdss_gpio1, +- qdss_gpio10, qdss_gpio11, qdss_gpio12, qdss_gpio13, qdss_gpio14, +- qdss_gpio15, qdss_gpio2, qdss_gpio3, qdss_gpio4, qdss_gpio5, +- qdss_gpio6, qdss_gpio7, qdss_gpio8, qdss_gpio9, qlink0_enable, +- qlink0_request, qlink0_wmss, qlink1_enable, qlink1_request, +- qlink1_wmss, qlink2_enable, qlink2_request, qlink2_wmss, +- qup0_se0, qup0_se1, qup0_se2, qup0_se3, qup0_se4, qup0_se5, +- qup0_se6, qup0_se7, qup1_se0, qup1_se1, qup1_se2, qup1_se3, +- qup1_se4, qup1_se5, qup1_se6, sd_write, tb_trig, tgu_ch0, +- tgu_ch1, tgu_ch2, tgu_ch3, tmess_prng0, tmess_prng1, +- tmess_prng2, tmess_prng3, tsense_pwm1, tsense_pwm2, uim0_clk, +- uim0_data, uim0_present, uim0_reset, uim1_clk, uim1_data, +- uim1_present, uim1_reset, usb0_hs, usb0_phy, vfr_0, vfr_1, +- vsense_trigger ] ++ enum: [ gpio, atest_char, atest_usb0, audio_ref_clk, cam_mclk, ++ cci_async_in0, cci_i2c, cci, cmu_rng, coex_uart1_rx, ++ coex_uart1_tx, cri_trng, dbg_out_clk, ddr_bist, ++ ddr_pxi0_test, ddr_pxi1_test, gcc_gp1_clk, gcc_gp2_clk, ++ gcc_gp3_clk, host2wlan_sol, ibi_i3c_qup0, ibi_i3c_qup1, ++ jitter_bist_ref, mdp_vsync0_out, mdp_vsync1_out, ++ mdp_vsync2_out, mdp_vsync3_out, mdp_vsync, nav, ++ pcie0_clk_req, phase_flag, pll_bist_sync, pll_clk_aux, ++ prng_rosc, qdss_cti_trig0, qdss_cti_trig1, qdss_gpio, ++ qlink0_enable, qlink0_request, qlink0_wmss_reset, ++ qup0_se0, qup0_se1, qup0_se2, qup0_se3, qup0_se4, ++ qup1_se0, qup1_se1, qup1_se2, qup1_se2_l2, qup1_se3, ++ qup1_se4, sd_write_protect, tb_trig_sdc1, tb_trig_sdc2, ++ tgu_ch0_trigout, tgu_ch1_trigout, tgu_ch2_trigout, ++ tgu_ch3_trigout, tmess_prng, tsense_pwm1_out, ++ tsense_pwm2_out, uim0, uim1, usb0_hs_ac, usb0_phy_ps, ++ vfr_0_mira, vfr_0_mirb, vfr_1, vsense_trigger_mirnat, ++ wlan1_adc_dtest0, wlan1_adc_dtest1 ] + + required: + - pins +diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst +index 6042085340953..833f68fb07008 100644 +--- a/Documentation/driver-api/fpga/fpga-bridge.rst ++++ b/Documentation/driver-api/fpga/fpga-bridge.rst +@@ -6,9 +6,12 @@ API to implement a new FPGA bridge + + * struct fpga_bridge - The FPGA Bridge structure + * struct fpga_bridge_ops - Low level Bridge driver ops +-* fpga_bridge_register() - Create and register a bridge ++* __fpga_bridge_register() - Create and register a bridge + * fpga_bridge_unregister() - Unregister a bridge + ++The helper macro ``fpga_bridge_register()`` automatically sets ++the module that registers the FPGA bridge as the owner. ++ + .. kernel-doc:: include/linux/fpga/fpga-bridge.h + :functions: fpga_bridge + +@@ -16,7 +19,7 @@ API to implement a new FPGA bridge + :functions: fpga_bridge_ops + + .. kernel-doc:: drivers/fpga/fpga-bridge.c +- :functions: fpga_bridge_register ++ :functions: __fpga_bridge_register + + .. kernel-doc:: drivers/fpga/fpga-bridge.c + :functions: fpga_bridge_unregister +diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst +index 49c0a95126532..8d2b79f696c1f 100644 +--- a/Documentation/driver-api/fpga/fpga-mgr.rst ++++ b/Documentation/driver-api/fpga/fpga-mgr.rst +@@ -24,7 +24,8 @@ How to support a new FPGA device + -------------------------------- + + To add another FPGA manager, write a driver that implements a set of ops. The +-probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as:: ++probe function calls ``fpga_mgr_register()`` or ``fpga_mgr_register_full()``, ++such as:: + + static const struct fpga_manager_ops socfpga_fpga_ops = { + .write_init = socfpga_fpga_ops_configure_init, +@@ -69,10 +70,11 @@ probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as:: + } + + Alternatively, the probe function could call one of the resource managed +-register functions, devm_fpga_mgr_register() or devm_fpga_mgr_register_full(). +-When these functions are used, the parameter syntax is the same, but the call +-to fpga_mgr_unregister() should be removed. In the above example, the +-socfpga_fpga_remove() function would not be required. ++register functions, ``devm_fpga_mgr_register()`` or ++``devm_fpga_mgr_register_full()``. When these functions are used, the ++parameter syntax is the same, but the call to ``fpga_mgr_unregister()`` should be ++removed. In the above example, the ``socfpga_fpga_remove()`` function would not be ++required. + + The ops will implement whatever device specific register writes are needed to + do the programming sequence for this particular FPGA. These ops return 0 for +@@ -125,15 +127,19 @@ API for implementing a new FPGA Manager driver + * struct fpga_manager - the FPGA manager struct + * struct fpga_manager_ops - Low level FPGA manager driver ops + * struct fpga_manager_info - Parameter structure for fpga_mgr_register_full() +-* fpga_mgr_register_full() - Create and register an FPGA manager using the ++* __fpga_mgr_register_full() - Create and register an FPGA manager using the + fpga_mgr_info structure to provide the full flexibility of options +-* fpga_mgr_register() - Create and register an FPGA manager using standard ++* __fpga_mgr_register() - Create and register an FPGA manager using standard + arguments +-* devm_fpga_mgr_register_full() - Resource managed version of +- fpga_mgr_register_full() +-* devm_fpga_mgr_register() - Resource managed version of fpga_mgr_register() ++* __devm_fpga_mgr_register_full() - Resource managed version of ++ __fpga_mgr_register_full() ++* __devm_fpga_mgr_register() - Resource managed version of __fpga_mgr_register() + * fpga_mgr_unregister() - Unregister an FPGA manager + ++Helper macros ``fpga_mgr_register_full()``, ``fpga_mgr_register()``, ++``devm_fpga_mgr_register_full()``, and ``devm_fpga_mgr_register()`` are available ++to ease the registration. ++ + .. kernel-doc:: include/linux/fpga/fpga-mgr.h + :functions: fpga_mgr_states + +@@ -147,16 +153,16 @@ API for implementing a new FPGA Manager driver + :functions: fpga_manager_info + + .. kernel-doc:: drivers/fpga/fpga-mgr.c +- :functions: fpga_mgr_register_full ++ :functions: __fpga_mgr_register_full + + .. kernel-doc:: drivers/fpga/fpga-mgr.c +- :functions: fpga_mgr_register ++ :functions: __fpga_mgr_register + + .. kernel-doc:: drivers/fpga/fpga-mgr.c +- :functions: devm_fpga_mgr_register_full ++ :functions: __devm_fpga_mgr_register_full + + .. kernel-doc:: drivers/fpga/fpga-mgr.c +- :functions: devm_fpga_mgr_register ++ :functions: __devm_fpga_mgr_register + + .. kernel-doc:: drivers/fpga/fpga-mgr.c + :functions: fpga_mgr_unregister +diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst +index dc55d60a0b4a5..2d03b5fb76575 100644 +--- a/Documentation/driver-api/fpga/fpga-region.rst ++++ b/Documentation/driver-api/fpga/fpga-region.rst +@@ -46,13 +46,16 @@ API to add a new FPGA region + ---------------------------- + + * struct fpga_region - The FPGA region struct +-* struct fpga_region_info - Parameter structure for fpga_region_register_full() +-* fpga_region_register_full() - Create and register an FPGA region using the ++* struct fpga_region_info - Parameter structure for __fpga_region_register_full() ++* __fpga_region_register_full() - Create and register an FPGA region using the + fpga_region_info structure to provide the full flexibility of options +-* fpga_region_register() - Create and register an FPGA region using standard ++* __fpga_region_register() - Create and register an FPGA region using standard + arguments + * fpga_region_unregister() - Unregister an FPGA region + ++Helper macros ``fpga_region_register()`` and ``fpga_region_register_full()`` ++automatically set the module that registers the FPGA region as the owner. ++ + The FPGA region's probe function will need to get a reference to the FPGA + Manager it will be using to do the programming. This usually would happen + during the region's probe function. +@@ -82,10 +85,10 @@ following APIs to handle building or tearing down that list. + :functions: fpga_region_info + + .. kernel-doc:: drivers/fpga/fpga-region.c +- :functions: fpga_region_register_full ++ :functions: __fpga_region_register_full + + .. kernel-doc:: drivers/fpga/fpga-region.c +- :functions: fpga_region_register ++ :functions: __fpga_region_register + + .. kernel-doc:: drivers/fpga/fpga-region.c + :functions: fpga_region_unregister +diff --git a/Documentation/iio/adis16475.rst b/Documentation/iio/adis16475.rst +index 91cabb7d8d057..130f9e97cc17c 100644 +--- a/Documentation/iio/adis16475.rst ++++ b/Documentation/iio/adis16475.rst +@@ -66,11 +66,9 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. + +-------------------------------------------+----------------------------------------------------------+ + | in_accel_x_calibbias | Calibration offset for the X-axis accelerometer channel. | + +-------------------------------------------+----------------------------------------------------------+ +-| in_accel_calibbias_x | x-axis acceleration offset correction | +-+-------------------------------------------+----------------------------------------------------------+ + | in_accel_x_raw | Raw X-axis accelerometer channel value. | + +-------------------------------------------+----------------------------------------------------------+ +-| in_accel_calibbias_y | y-axis acceleration offset correction | ++| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. | + +-------------------------------------------+----------------------------------------------------------+ + | in_accel_y_raw | Raw Y-axis accelerometer channel value. | + +-------------------------------------------+----------------------------------------------------------+ +@@ -94,11 +92,9 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. + +---------------------------------------+------------------------------------------------------+ + | in_anglvel_x_calibbias | Calibration offset for the X-axis gyroscope channel. | + +---------------------------------------+------------------------------------------------------+ +-| in_anglvel_calibbias_x | x-axis gyroscope offset correction | +-+---------------------------------------+------------------------------------------------------+ + | in_anglvel_x_raw | Raw X-axis gyroscope channel value. | + +---------------------------------------+------------------------------------------------------+ +-| in_anglvel_calibbias_y | y-axis gyroscope offset correction | ++| in_anglvel_y_calibbias | Calibration offset for the Y-axis gyroscope channel. | + +---------------------------------------+------------------------------------------------------+ + | in_anglvel_y_raw | Raw Y-axis gyroscope channel value. | + +---------------------------------------+------------------------------------------------------+ +diff --git a/Makefile b/Makefile +index 8def0819eb55b..91f1d4d34e809 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 9 +-SUBLEVEL = 3 ++SUBLEVEL = 4 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi +index ce90b35686a21..10896f9df682d 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi +@@ -65,10 +65,15 @@ xtal: xtal-clk { + #clock-cells = <0>; + }; + +- pwrc: power-controller { +- compatible = "amlogic,meson-s4-pwrc"; +- #power-domain-cells = <1>; +- status = "okay"; ++ firmware { ++ sm: secure-monitor { ++ compatible = "amlogic,meson-gxbb-sm"; ++ ++ pwrc: power-controller { ++ compatible = "amlogic,meson-s4-pwrc"; ++ #power-domain-cells = <1>; ++ }; ++ }; + }; + + soc { +diff --git a/arch/arm64/include/asm/asm-bug.h b/arch/arm64/include/asm/asm-bug.h +index c762038ba4009..6e73809f6492a 100644 +--- a/arch/arm64/include/asm/asm-bug.h ++++ b/arch/arm64/include/asm/asm-bug.h +@@ -28,6 +28,7 @@ + 14470: .long 14471f - .; \ + _BUGVERBOSE_LOCATION(__FILE__, __LINE__) \ + .short flags; \ ++ .align 2; \ + .popsection; \ + 14471: + #else +diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c +index c4a0a35e02c72..6cda738a41577 100644 +--- a/arch/arm64/kvm/arm.c ++++ b/arch/arm64/kvm/arm.c +@@ -195,6 +195,23 @@ void kvm_arch_create_vm_debugfs(struct kvm *kvm) + kvm_sys_regs_create_debugfs(kvm); + } + ++static void kvm_destroy_mpidr_data(struct kvm *kvm) ++{ ++ struct kvm_mpidr_data *data; ++ ++ mutex_lock(&kvm->arch.config_lock); ++ ++ data = rcu_dereference_protected(kvm->arch.mpidr_data, ++ lockdep_is_held(&kvm->arch.config_lock)); ++ if (data) { ++ rcu_assign_pointer(kvm->arch.mpidr_data, NULL); ++ synchronize_rcu(); ++ kfree(data); ++ } ++ ++ mutex_unlock(&kvm->arch.config_lock); ++} ++ + /** + * kvm_arch_destroy_vm - destroy the VM data structure + * @kvm: pointer to the KVM struct +@@ -209,7 +226,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm) + if (is_protected_kvm_enabled()) + pkvm_destroy_hyp_vm(kvm); + +- kfree(kvm->arch.mpidr_data); ++ kvm_destroy_mpidr_data(kvm); ++ + kfree(kvm->arch.sysreg_masks); + kvm_destroy_vcpus(kvm); + +@@ -395,6 +413,13 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) + + vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu; + ++ /* ++ * This vCPU may have been created after mpidr_data was initialized. ++ * Throw out the pre-computed mappings if that is the case which forces ++ * KVM to fall back to iteratively searching the vCPUs. ++ */ ++ kvm_destroy_mpidr_data(vcpu->kvm); ++ + err = kvm_vgic_vcpu_init(vcpu); + if (err) + return err; +@@ -594,7 +619,8 @@ static void kvm_init_mpidr_data(struct kvm *kvm) + + mutex_lock(&kvm->arch.config_lock); + +- if (kvm->arch.mpidr_data || atomic_read(&kvm->online_vcpus) == 1) ++ if (rcu_access_pointer(kvm->arch.mpidr_data) || ++ atomic_read(&kvm->online_vcpus) == 1) + goto out; + + kvm_for_each_vcpu(c, vcpu, kvm) { +@@ -631,7 +657,7 @@ static void kvm_init_mpidr_data(struct kvm *kvm) + data->cmpidr_to_idx[index] = c; + } + +- kvm->arch.mpidr_data = data; ++ rcu_assign_pointer(kvm->arch.mpidr_data, data); + out: + mutex_unlock(&kvm->arch.config_lock); + } +@@ -2470,21 +2496,27 @@ static int __init init_hyp_mode(void) + + struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr) + { +- struct kvm_vcpu *vcpu; ++ struct kvm_vcpu *vcpu = NULL; ++ struct kvm_mpidr_data *data; + unsigned long i; + + mpidr &= MPIDR_HWID_BITMASK; + +- if (kvm->arch.mpidr_data) { +- u16 idx = kvm_mpidr_index(kvm->arch.mpidr_data, mpidr); ++ rcu_read_lock(); ++ data = rcu_dereference(kvm->arch.mpidr_data); + +- vcpu = kvm_get_vcpu(kvm, +- kvm->arch.mpidr_data->cmpidr_to_idx[idx]); ++ if (data) { ++ u16 idx = kvm_mpidr_index(data, mpidr); ++ ++ vcpu = kvm_get_vcpu(kvm, data->cmpidr_to_idx[idx]); + if (mpidr != kvm_vcpu_get_mpidr_aff(vcpu)) + vcpu = NULL; ++ } + ++ rcu_read_unlock(); ++ ++ if (vcpu) + return vcpu; +- } + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (mpidr == kvm_vcpu_get_mpidr_aff(vcpu)) +diff --git a/arch/loongarch/include/asm/perf_event.h b/arch/loongarch/include/asm/perf_event.h +index 52b638059e40b..f948a0676daf8 100644 +--- a/arch/loongarch/include/asm/perf_event.h ++++ b/arch/loongarch/include/asm/perf_event.h +@@ -13,8 +13,7 @@ + + #define perf_arch_fetch_caller_regs(regs, __ip) { \ + (regs)->csr_era = (__ip); \ +- (regs)->regs[3] = current_stack_pointer; \ +- (regs)->regs[22] = (unsigned long) __builtin_frame_address(0); \ ++ (regs)->regs[3] = (unsigned long) __builtin_frame_address(0); \ + } + + #endif /* __LOONGARCH_PERF_EVENT_H__ */ +diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile +index 4393bee64eaf8..85c4d29ef43e9 100644 +--- a/arch/microblaze/kernel/Makefile ++++ b/arch/microblaze/kernel/Makefile +@@ -7,7 +7,6 @@ ifdef CONFIG_FUNCTION_TRACER + # Do not trace early boot code and low level code + CFLAGS_REMOVE_timer.o = -pg + CFLAGS_REMOVE_intc.o = -pg +-CFLAGS_REMOVE_early_printk.o = -pg + CFLAGS_REMOVE_ftrace.o = -pg + CFLAGS_REMOVE_process.o = -pg + endif +diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c +index 85dbda4a08a81..03da36dc6d9c9 100644 +--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c ++++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c +@@ -18,7 +18,7 @@ static const char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY; + static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER; + + #define err_printk(x) \ +- early_printk("ERROR: Microblaze " x "-different for kernel and DTS\n"); ++ pr_err("ERROR: Microblaze " x "-different for kernel and DTS\n"); + + void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) + { +diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h +index a41e542ba94dd..51172625fa3a5 100644 +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -570,7 +570,7 @@ struct hvcall_mpp_data { + unsigned long backing_mem; + }; + +-int h_get_mpp(struct hvcall_mpp_data *); ++long h_get_mpp(struct hvcall_mpp_data *mpp_data); + + struct hvcall_mpp_x_data { + unsigned long coalesced_bytes; +diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h +index 005601243dda4..076ae60b4a55d 100644 +--- a/arch/powerpc/include/asm/ppc-opcode.h ++++ b/arch/powerpc/include/asm/ppc-opcode.h +@@ -510,6 +510,7 @@ + #define PPC_RAW_STB(r, base, i) (0x98000000 | ___PPC_RS(r) | ___PPC_RA(base) | IMM_L(i)) + #define PPC_RAW_LBZ(r, base, i) (0x88000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) + #define PPC_RAW_LDX(r, base, b) (0x7c00002a | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b)) ++#define PPC_RAW_LHA(r, base, i) (0xa8000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) + #define PPC_RAW_LHZ(r, base, i) (0xa0000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) + #define PPC_RAW_LHBRX(r, base, b) (0x7c00062c | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b)) + #define PPC_RAW_LWBRX(r, base, b) (0x7c00042c | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b)) +@@ -532,6 +533,7 @@ + #define PPC_RAW_MULW(d, a, b) (0x7c0001d6 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) + #define PPC_RAW_MULHWU(d, a, b) (0x7c000016 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) + #define PPC_RAW_MULI(d, a, i) (0x1c000000 | ___PPC_RT(d) | ___PPC_RA(a) | IMM_L(i)) ++#define PPC_RAW_DIVW(d, a, b) (0x7c0003d6 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) + #define PPC_RAW_DIVWU(d, a, b) (0x7c000396 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) + #define PPC_RAW_DIVDU(d, a, b) (0x7c000392 | ___PPC_RT(d) | ___PPC_RA(a) | ___PPC_RB(b)) + #define PPC_RAW_DIVDE(t, a, b) (0x7c000352 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) +@@ -550,6 +552,8 @@ + #define PPC_RAW_XOR(d, a, b) (0x7c000278 | ___PPC_RA(d) | ___PPC_RS(a) | ___PPC_RB(b)) + #define PPC_RAW_XORI(d, a, i) (0x68000000 | ___PPC_RA(d) | ___PPC_RS(a) | IMM_L(i)) + #define PPC_RAW_XORIS(d, a, i) (0x6c000000 | ___PPC_RA(d) | ___PPC_RS(a) | IMM_L(i)) ++#define PPC_RAW_EXTSB(d, a) (0x7c000774 | ___PPC_RA(d) | ___PPC_RS(a)) ++#define PPC_RAW_EXTSH(d, a) (0x7c000734 | ___PPC_RA(d) | ___PPC_RS(a)) + #define PPC_RAW_EXTSW(d, a) (0x7c0007b4 | ___PPC_RA(d) | ___PPC_RS(a)) + #define PPC_RAW_SLW(d, a, s) (0x7c000030 | ___PPC_RA(d) | ___PPC_RS(a) | ___PPC_RB(s)) + #define PPC_RAW_SLD(d, a, s) (0x7c000036 | ___PPC_RA(d) | ___PPC_RS(a) | ___PPC_RB(s)) +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 8e86eb577eb8e..692a7c6f5fd91 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -4857,7 +4857,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + * entering a nested guest in which case the decrementer is now owned + * by L2 and the L1 decrementer is provided in hdec_expires + */ +- if (!kvmhv_is_nestedv2() && kvmppc_core_pending_dec(vcpu) && ++ if (kvmppc_core_pending_dec(vcpu) && + ((tb < kvmppc_dec_expires_host_tb(vcpu)) || + (trap == BOOK3S_INTERRUPT_SYSCALL && + kvmppc_get_gpr(vcpu, 3) == H_ENTER_NESTED))) +diff --git a/arch/powerpc/kvm/book3s_hv_nestedv2.c b/arch/powerpc/kvm/book3s_hv_nestedv2.c +index 8e6f5355f08b5..1091f7a83b255 100644 +--- a/arch/powerpc/kvm/book3s_hv_nestedv2.c ++++ b/arch/powerpc/kvm/book3s_hv_nestedv2.c +@@ -71,8 +71,8 @@ gs_msg_ops_kvmhv_nestedv2_config_fill_info(struct kvmppc_gs_buff *gsb, + } + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT)) { +- kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_OUTPUT, +- cfg->vcpu_run_output_cfg); ++ rc = kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_OUTPUT, ++ cfg->vcpu_run_output_cfg); + if (rc < 0) + return rc; + } +diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c +index 2f39c50ca729e..43b97032a91c0 100644 +--- a/arch/powerpc/net/bpf_jit_comp32.c ++++ b/arch/powerpc/net/bpf_jit_comp32.c +@@ -450,10 +450,16 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + } + break; + case BPF_ALU | BPF_DIV | BPF_X: /* (u32) dst /= (u32) src */ +- EMIT(PPC_RAW_DIVWU(dst_reg, src2_reg, src_reg)); ++ if (off) ++ EMIT(PPC_RAW_DIVW(dst_reg, src2_reg, src_reg)); ++ else ++ EMIT(PPC_RAW_DIVWU(dst_reg, src2_reg, src_reg)); + break; + case BPF_ALU | BPF_MOD | BPF_X: /* (u32) dst %= (u32) src */ +- EMIT(PPC_RAW_DIVWU(_R0, src2_reg, src_reg)); ++ if (off) ++ EMIT(PPC_RAW_DIVW(_R0, src2_reg, src_reg)); ++ else ++ EMIT(PPC_RAW_DIVWU(_R0, src2_reg, src_reg)); + EMIT(PPC_RAW_MULW(_R0, src_reg, _R0)); + EMIT(PPC_RAW_SUB(dst_reg, src2_reg, _R0)); + break; +@@ -467,10 +473,16 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + if (imm == 1) { + EMIT(PPC_RAW_MR(dst_reg, src2_reg)); + } else if (is_power_of_2((u32)imm)) { +- EMIT(PPC_RAW_SRWI(dst_reg, src2_reg, ilog2(imm))); ++ if (off) ++ EMIT(PPC_RAW_SRAWI(dst_reg, src2_reg, ilog2(imm))); ++ else ++ EMIT(PPC_RAW_SRWI(dst_reg, src2_reg, ilog2(imm))); + } else { + PPC_LI32(_R0, imm); +- EMIT(PPC_RAW_DIVWU(dst_reg, src2_reg, _R0)); ++ if (off) ++ EMIT(PPC_RAW_DIVW(dst_reg, src2_reg, _R0)); ++ else ++ EMIT(PPC_RAW_DIVWU(dst_reg, src2_reg, _R0)); + } + break; + case BPF_ALU | BPF_MOD | BPF_K: /* (u32) dst %= (u32) imm */ +@@ -480,11 +492,19 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + if (!is_power_of_2((u32)imm)) { + bpf_set_seen_register(ctx, tmp_reg); + PPC_LI32(tmp_reg, imm); +- EMIT(PPC_RAW_DIVWU(_R0, src2_reg, tmp_reg)); ++ if (off) ++ EMIT(PPC_RAW_DIVW(_R0, src2_reg, tmp_reg)); ++ else ++ EMIT(PPC_RAW_DIVWU(_R0, src2_reg, tmp_reg)); + EMIT(PPC_RAW_MULW(_R0, tmp_reg, _R0)); + EMIT(PPC_RAW_SUB(dst_reg, src2_reg, _R0)); + } else if (imm == 1) { + EMIT(PPC_RAW_LI(dst_reg, 0)); ++ } else if (off) { ++ EMIT(PPC_RAW_SRAWI(_R0, src2_reg, ilog2(imm))); ++ EMIT(PPC_RAW_ADDZE(_R0, _R0)); ++ EMIT(PPC_RAW_SLWI(_R0, _R0, ilog2(imm))); ++ EMIT(PPC_RAW_SUB(dst_reg, src2_reg, _R0)); + } else { + imm = ilog2((u32)imm); + EMIT(PPC_RAW_RLWINM(dst_reg, src2_reg, 0, 32 - imm, 31)); +@@ -497,11 +517,21 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + imm = -imm; + if (!is_power_of_2(imm)) + return -EOPNOTSUPP; +- if (imm == 1) ++ if (imm == 1) { + EMIT(PPC_RAW_LI(dst_reg, 0)); +- else ++ EMIT(PPC_RAW_LI(dst_reg_h, 0)); ++ } else if (off) { ++ EMIT(PPC_RAW_SRAWI(dst_reg_h, src2_reg_h, 31)); ++ EMIT(PPC_RAW_XOR(dst_reg, src2_reg, dst_reg_h)); ++ EMIT(PPC_RAW_SUBFC(dst_reg, dst_reg_h, dst_reg)); ++ EMIT(PPC_RAW_RLWINM(dst_reg, dst_reg, 0, 32 - ilog2(imm), 31)); ++ EMIT(PPC_RAW_XOR(dst_reg, dst_reg, dst_reg_h)); ++ EMIT(PPC_RAW_SUBFC(dst_reg, dst_reg_h, dst_reg)); ++ EMIT(PPC_RAW_SUBFE(dst_reg_h, dst_reg_h, dst_reg_h)); ++ } else { + EMIT(PPC_RAW_RLWINM(dst_reg, src2_reg, 0, 32 - ilog2(imm), 31)); +- EMIT(PPC_RAW_LI(dst_reg_h, 0)); ++ EMIT(PPC_RAW_LI(dst_reg_h, 0)); ++ } + break; + case BPF_ALU64 | BPF_DIV | BPF_K: /* dst /= imm */ + if (!imm) +@@ -727,15 +757,30 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + * MOV + */ + case BPF_ALU64 | BPF_MOV | BPF_X: /* dst = src */ +- if (dst_reg == src_reg) +- break; +- EMIT(PPC_RAW_MR(dst_reg, src_reg)); +- EMIT(PPC_RAW_MR(dst_reg_h, src_reg_h)); ++ if (off == 8) { ++ EMIT(PPC_RAW_EXTSB(dst_reg, src_reg)); ++ EMIT(PPC_RAW_SRAWI(dst_reg_h, dst_reg, 31)); ++ } else if (off == 16) { ++ EMIT(PPC_RAW_EXTSH(dst_reg, src_reg)); ++ EMIT(PPC_RAW_SRAWI(dst_reg_h, dst_reg, 31)); ++ } else if (off == 32 && dst_reg == src_reg) { ++ EMIT(PPC_RAW_SRAWI(dst_reg_h, src_reg, 31)); ++ } else if (off == 32) { ++ EMIT(PPC_RAW_MR(dst_reg, src_reg)); ++ EMIT(PPC_RAW_SRAWI(dst_reg_h, src_reg, 31)); ++ } else if (dst_reg != src_reg) { ++ EMIT(PPC_RAW_MR(dst_reg, src_reg)); ++ EMIT(PPC_RAW_MR(dst_reg_h, src_reg_h)); ++ } + break; + case BPF_ALU | BPF_MOV | BPF_X: /* (u32) dst = src */ + /* special mov32 for zext */ + if (imm == 1) + EMIT(PPC_RAW_LI(dst_reg_h, 0)); ++ else if (off == 8) ++ EMIT(PPC_RAW_EXTSB(dst_reg, src_reg)); ++ else if (off == 16) ++ EMIT(PPC_RAW_EXTSH(dst_reg, src_reg)); + else if (dst_reg != src_reg) + EMIT(PPC_RAW_MR(dst_reg, src_reg)); + break; +@@ -751,6 +796,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + * BPF_FROM_BE/LE + */ + case BPF_ALU | BPF_END | BPF_FROM_LE: ++ case BPF_ALU64 | BPF_END | BPF_FROM_LE: + switch (imm) { + case 16: + /* Copy 16 bits to upper part */ +@@ -785,6 +831,8 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + EMIT(PPC_RAW_MR(dst_reg_h, tmp_reg)); + break; + } ++ if (BPF_CLASS(code) == BPF_ALU64 && imm != 64) ++ EMIT(PPC_RAW_LI(dst_reg_h, 0)); + break; + case BPF_ALU | BPF_END | BPF_FROM_BE: + switch (imm) { +@@ -918,11 +966,17 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + * BPF_LDX + */ + case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */ ++ case BPF_LDX | BPF_MEMSX | BPF_B: + case BPF_LDX | BPF_PROBE_MEM | BPF_B: ++ case BPF_LDX | BPF_PROBE_MEMSX | BPF_B: + case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */ ++ case BPF_LDX | BPF_MEMSX | BPF_H: + case BPF_LDX | BPF_PROBE_MEM | BPF_H: ++ case BPF_LDX | BPF_PROBE_MEMSX | BPF_H: + case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */ ++ case BPF_LDX | BPF_MEMSX | BPF_W: + case BPF_LDX | BPF_PROBE_MEM | BPF_W: ++ case BPF_LDX | BPF_PROBE_MEMSX | BPF_W: + case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */ + case BPF_LDX | BPF_PROBE_MEM | BPF_DW: + /* +@@ -931,7 +985,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + * load only if addr is kernel address (see is_kernel_addr()), otherwise + * set dst_reg=0 and move on. + */ +- if (BPF_MODE(code) == BPF_PROBE_MEM) { ++ if (BPF_MODE(code) == BPF_PROBE_MEM || BPF_MODE(code) == BPF_PROBE_MEMSX) { + PPC_LI32(_R0, TASK_SIZE - off); + EMIT(PPC_RAW_CMPLW(src_reg, _R0)); + PPC_BCC_SHORT(COND_GT, (ctx->idx + 4) * 4); +@@ -953,30 +1007,48 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + * as there are two load instructions for dst_reg_h & dst_reg + * respectively. + */ +- if (size == BPF_DW) ++ if (size == BPF_DW || ++ (size == BPF_B && BPF_MODE(code) == BPF_PROBE_MEMSX)) + PPC_JMP((ctx->idx + 3) * 4); + else + PPC_JMP((ctx->idx + 2) * 4); + } + +- switch (size) { +- case BPF_B: +- EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off)); +- break; +- case BPF_H: +- EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off)); +- break; +- case BPF_W: +- EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off)); +- break; +- case BPF_DW: +- EMIT(PPC_RAW_LWZ(dst_reg_h, src_reg, off)); +- EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off + 4)); +- break; +- } ++ if (BPF_MODE(code) == BPF_MEMSX || BPF_MODE(code) == BPF_PROBE_MEMSX) { ++ switch (size) { ++ case BPF_B: ++ EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off)); ++ EMIT(PPC_RAW_EXTSB(dst_reg, dst_reg)); ++ break; ++ case BPF_H: ++ EMIT(PPC_RAW_LHA(dst_reg, src_reg, off)); ++ break; ++ case BPF_W: ++ EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off)); ++ break; ++ } ++ if (!fp->aux->verifier_zext) ++ EMIT(PPC_RAW_SRAWI(dst_reg_h, dst_reg, 31)); + +- if (size != BPF_DW && !fp->aux->verifier_zext) +- EMIT(PPC_RAW_LI(dst_reg_h, 0)); ++ } else { ++ switch (size) { ++ case BPF_B: ++ EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off)); ++ break; ++ case BPF_H: ++ EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off)); ++ break; ++ case BPF_W: ++ EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off)); ++ break; ++ case BPF_DW: ++ EMIT(PPC_RAW_LWZ(dst_reg_h, src_reg, off)); ++ EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off + 4)); ++ break; ++ } ++ if (size != BPF_DW && !fp->aux->verifier_zext) ++ EMIT(PPC_RAW_LI(dst_reg_h, 0)); ++ } + + if (BPF_MODE(code) == BPF_PROBE_MEM) { + int insn_idx = ctx->idx - 1; +@@ -1068,6 +1140,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code + case BPF_JMP | BPF_JA: + PPC_JMP(addrs[i + 1 + off]); + break; ++ case BPF_JMP32 | BPF_JA: ++ PPC_JMP(addrs[i + 1 + imm]); ++ break; + + case BPF_JMP | BPF_JGT | BPF_K: + case BPF_JMP | BPF_JGT | BPF_X: +diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c +index 4e9916bb03d71..c1d8bee8f7018 100644 +--- a/arch/powerpc/platforms/pseries/lpar.c ++++ b/arch/powerpc/platforms/pseries/lpar.c +@@ -1886,10 +1886,10 @@ notrace void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf) + * h_get_mpp + * H_GET_MPP hcall returns info in 7 parms + */ +-int h_get_mpp(struct hvcall_mpp_data *mpp_data) ++long h_get_mpp(struct hvcall_mpp_data *mpp_data) + { +- int rc; +- unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; ++ unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; ++ long rc; + + rc = plpar_hcall9(H_GET_MPP, retbuf); + +diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c +index f73c4d1c26af9..0ed56e56271fe 100644 +--- a/arch/powerpc/platforms/pseries/lparcfg.c ++++ b/arch/powerpc/platforms/pseries/lparcfg.c +@@ -113,8 +113,8 @@ struct hvcall_ppp_data { + */ + static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data) + { +- unsigned long rc; +- unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; ++ unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0}; ++ long rc; + + rc = plpar_hcall9(H_GET_PPP, retbuf); + +@@ -193,7 +193,7 @@ static void parse_ppp_data(struct seq_file *m) + struct hvcall_ppp_data ppp_data; + struct device_node *root; + const __be32 *perf_level; +- int rc; ++ long rc; + + rc = h_get_ppp(&ppp_data); + if (rc) +@@ -361,8 +361,8 @@ static int read_dt_lpar_name(struct seq_file *m) + + static void read_lpar_name(struct seq_file *m) + { +- if (read_rtas_lpar_name(m) && read_dt_lpar_name(m)) +- pr_err_once("Error can't get the LPAR name"); ++ if (read_rtas_lpar_name(m)) ++ read_dt_lpar_name(m); + } + + #define SPLPAR_MAXLENGTH 1026*(sizeof(char)) +diff --git a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +index 45b58b6f3df88..2b3e952513e44 100644 +--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi ++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi +@@ -279,24 +279,6 @@ &i2c6 { + status = "okay"; + }; + +-&i2srx { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2srx_pins>; +- status = "okay"; +-}; +- +-&i2stx0 { +- pinctrl-names = "default"; +- pinctrl-0 = <&mclk_ext_pins>; +- status = "okay"; +-}; +- +-&i2stx1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2stx1_pins>; +- status = "okay"; +-}; +- + &mmc0 { + max-frequency = <100000000>; + assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>; +@@ -447,46 +429,6 @@ GPOEN_SYS_I2C6_DATA, + }; + }; + +- i2srx_pins: i2srx-0 { +- clk-sd-pins { +- pinmux = <GPIOMUX(38, GPOUT_LOW, +- GPOEN_DISABLE, +- GPI_SYS_I2SRX_BCLK)>, +- <GPIOMUX(63, GPOUT_LOW, +- GPOEN_DISABLE, +- GPI_SYS_I2SRX_LRCK)>, +- <GPIOMUX(38, GPOUT_LOW, +- GPOEN_DISABLE, +- GPI_SYS_I2STX1_BCLK)>, +- <GPIOMUX(63, GPOUT_LOW, +- GPOEN_DISABLE, +- GPI_SYS_I2STX1_LRCK)>, +- <GPIOMUX(61, GPOUT_LOW, +- GPOEN_DISABLE, +- GPI_SYS_I2SRX_SDIN0)>; +- input-enable; +- }; +- }; +- +- i2stx1_pins: i2stx1-0 { +- sd-pins { +- pinmux = <GPIOMUX(44, GPOUT_SYS_I2STX1_SDO0, +- GPOEN_ENABLE, +- GPI_NONE)>; +- bias-disable; +- input-disable; +- }; +- }; +- +- mclk_ext_pins: mclk-ext-0 { +- mclk-ext-pins { +- pinmux = <GPIOMUX(4, GPOUT_LOW, +- GPOEN_DISABLE, +- GPI_SYS_MCLK_EXT)>; +- input-enable; +- }; +- }; +- + mmc0_pins: mmc0-0 { + rst-pins { + pinmux = <GPIOMUX(62, GPOUT_SYS_SDIO0_RST, +@@ -622,40 +564,6 @@ GPOEN_ENABLE, + }; + }; + +- tdm_pins: tdm-0 { +- tx-pins { +- pinmux = <GPIOMUX(44, GPOUT_SYS_TDM_TXD, +- GPOEN_ENABLE, +- GPI_NONE)>; +- bias-pull-up; +- drive-strength = <2>; +- input-disable; +- input-schmitt-disable; +- slew-rate = <0>; +- }; +- +- rx-pins { +- pinmux = <GPIOMUX(61, GPOUT_HIGH, +- GPOEN_DISABLE, +- GPI_SYS_TDM_RXD)>; +- input-enable; +- }; +- +- sync-pins { +- pinmux = <GPIOMUX(63, GPOUT_HIGH, +- GPOEN_DISABLE, +- GPI_SYS_TDM_SYNC)>; +- input-enable; +- }; +- +- pcmclk-pins { +- pinmux = <GPIOMUX(38, GPOUT_HIGH, +- GPOEN_DISABLE, +- GPI_SYS_TDM_CLK)>; +- input-enable; +- }; +- }; +- + uart0_pins: uart0-0 { + tx-pins { + pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX, +@@ -681,12 +589,6 @@ GPOEN_DISABLE, + }; + }; + +-&tdm { +- pinctrl-names = "default"; +- pinctrl-0 = <&tdm_pins>; +- status = "okay"; +-}; +- + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; +diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h +index 6e68f8dff76bc..0fab508a65b3c 100644 +--- a/arch/riscv/include/asm/sbi.h ++++ b/arch/riscv/include/asm/sbi.h +@@ -370,6 +370,8 @@ static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1 + static inline void sbi_init(void) {} + #endif /* CONFIG_RISCV_SBI */ + ++unsigned long riscv_get_mvendorid(void); ++unsigned long riscv_get_marchid(void); + unsigned long riscv_cached_mvendorid(unsigned int cpu_id); + unsigned long riscv_cached_marchid(unsigned int cpu_id); + unsigned long riscv_cached_mimpid(unsigned int cpu_id); +diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c +index d11d6320fb0d2..c1f3655238fd2 100644 +--- a/arch/riscv/kernel/cpu.c ++++ b/arch/riscv/kernel/cpu.c +@@ -139,6 +139,34 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid) + return -1; + } + ++unsigned long __init riscv_get_marchid(void) ++{ ++ struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo); ++ ++#if IS_ENABLED(CONFIG_RISCV_SBI) ++ ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid(); ++#elif IS_ENABLED(CONFIG_RISCV_M_MODE) ++ ci->marchid = csr_read(CSR_MARCHID); ++#else ++ ci->marchid = 0; ++#endif ++ return ci->marchid; ++} ++ ++unsigned long __init riscv_get_mvendorid(void) ++{ ++ struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo); ++ ++#if IS_ENABLED(CONFIG_RISCV_SBI) ++ ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid(); ++#elif IS_ENABLED(CONFIG_RISCV_M_MODE) ++ ci->mvendorid = csr_read(CSR_MVENDORID); ++#else ++ ci->mvendorid = 0; ++#endif ++ return ci->mvendorid; ++} ++ + DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); + + unsigned long riscv_cached_mvendorid(unsigned int cpu_id) +@@ -170,12 +198,16 @@ static int riscv_cpuinfo_starting(unsigned int cpu) + struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo); + + #if IS_ENABLED(CONFIG_RISCV_SBI) +- ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid(); +- ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid(); ++ if (!ci->mvendorid) ++ ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid(); ++ if (!ci->marchid) ++ ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid(); + ci->mimpid = sbi_spec_is_0_1() ? 0 : sbi_get_mimpid(); + #elif IS_ENABLED(CONFIG_RISCV_M_MODE) +- ci->mvendorid = csr_read(CSR_MVENDORID); +- ci->marchid = csr_read(CSR_MARCHID); ++ if (!ci->mvendorid) ++ ci->mvendorid = csr_read(CSR_MVENDORID); ++ if (!ci->marchid) ++ ci->marchid = csr_read(CSR_MARCHID); + ci->mimpid = csr_read(CSR_MIMPID); + #else + ci->mvendorid = 0; +diff --git a/arch/riscv/kernel/cpu_ops_sbi.c b/arch/riscv/kernel/cpu_ops_sbi.c +index 1cc7df740eddc..e6fbaaf549562 100644 +--- a/arch/riscv/kernel/cpu_ops_sbi.c ++++ b/arch/riscv/kernel/cpu_ops_sbi.c +@@ -72,7 +72,7 @@ static int sbi_cpu_start(unsigned int cpuid, struct task_struct *tidle) + /* Make sure tidle is updated */ + smp_mb(); + bdata->task_ptr = tidle; +- bdata->stack_ptr = task_stack_page(tidle) + THREAD_SIZE; ++ bdata->stack_ptr = task_pt_regs(tidle); + /* Make sure boot data is updated */ + smp_mb(); + hsm_data = __pa(bdata); +diff --git a/arch/riscv/kernel/cpu_ops_spinwait.c b/arch/riscv/kernel/cpu_ops_spinwait.c +index 613872b0a21ac..24869eb889085 100644 +--- a/arch/riscv/kernel/cpu_ops_spinwait.c ++++ b/arch/riscv/kernel/cpu_ops_spinwait.c +@@ -34,8 +34,7 @@ static void cpu_update_secondary_bootdata(unsigned int cpuid, + + /* Make sure tidle is updated */ + smp_mb(); +- WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], +- task_stack_page(tidle) + THREAD_SIZE); ++ WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], task_pt_regs(tidle)); + WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle); + } + +diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c +index 3ed2359eae353..5ef48cb20ee11 100644 +--- a/arch/riscv/kernel/cpufeature.c ++++ b/arch/riscv/kernel/cpufeature.c +@@ -490,6 +490,8 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) + struct acpi_table_header *rhct; + acpi_status status; + unsigned int cpu; ++ u64 boot_vendorid; ++ u64 boot_archid; + + if (!acpi_disabled) { + status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct); +@@ -497,6 +499,9 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) + return; + } + ++ boot_vendorid = riscv_get_mvendorid(); ++ boot_archid = riscv_get_marchid(); ++ + for_each_possible_cpu(cpu) { + struct riscv_isainfo *isainfo = &hart_isa[cpu]; + unsigned long this_hwcap = 0; +@@ -544,8 +549,7 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) + * CPU cores with the ratified spec will contain non-zero + * marchid. + */ +- if (acpi_disabled && riscv_cached_mvendorid(cpu) == THEAD_VENDOR_ID && +- riscv_cached_marchid(cpu) == 0x0) { ++ if (acpi_disabled && boot_vendorid == THEAD_VENDOR_ID && boot_archid == 0x0) { + this_hwcap &= ~isa2hwcap[RISCV_ISA_EXT_v]; + clear_bit(RISCV_ISA_EXT_v, isainfo->isa); + } +@@ -599,7 +603,7 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap) + + if (ext->subset_ext_size) { + for (int j = 0; j < ext->subset_ext_size; j++) { +- if (riscv_isa_extension_check(ext->subset_ext_ids[i])) ++ if (riscv_isa_extension_check(ext->subset_ext_ids[j])) + set_bit(ext->subset_ext_ids[j], isainfo->isa); + } + } +diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c +index d41090fc32035..4b3c50da48ba1 100644 +--- a/arch/riscv/kernel/smpboot.c ++++ b/arch/riscv/kernel/smpboot.c +@@ -26,7 +26,7 @@ + #include <linux/sched/task_stack.h> + #include <linux/sched/mm.h> + +-#include <asm/cpufeature.h> ++#include <asm/cacheflush.h> + #include <asm/cpu_ops.h> + #include <asm/irq.h> + #include <asm/mmu_context.h> +@@ -234,9 +234,10 @@ asmlinkage __visible void smp_callin(void) + riscv_user_isa_enable(); + + /* +- * Remote TLB flushes are ignored while the CPU is offline, so emit +- * a local TLB flush right now just in case. ++ * Remote cache and TLB flushes are ignored while the CPU is offline, ++ * so flush them both right now just in case. + */ ++ local_flush_icache_all(); + local_flush_tlb_all(); + complete(&cpu_running); + /* +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index 64a9c093aef93..528ec7cc9a622 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -18,6 +18,16 @@ + + extern asmlinkage void ret_from_exception(void); + ++static inline int fp_is_valid(unsigned long fp, unsigned long sp) ++{ ++ unsigned long low, high; ++ ++ low = sp + sizeof(struct stackframe); ++ high = ALIGN(sp, THREAD_SIZE); ++ ++ return !(fp < low || fp > high || fp & 0x07); ++} ++ + void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + bool (*fn)(void *, unsigned long), void *arg) + { +@@ -41,21 +51,19 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + } + + for (;;) { +- unsigned long low, high; + struct stackframe *frame; + + if (unlikely(!__kernel_text_address(pc) || (level++ >= 0 && !fn(arg, pc)))) + break; + +- /* Validate frame pointer */ +- low = sp + sizeof(struct stackframe); +- high = ALIGN(sp, THREAD_SIZE); +- if (unlikely(fp < low || fp > high || fp & 0x7)) ++ if (unlikely(!fp_is_valid(fp, sp))) + break; ++ + /* Unwind stack frame */ + frame = (struct stackframe *)fp - 1; + sp = fp; +- if (regs && (regs->epc == pc) && (frame->fp & 0x7)) { ++ if (regs && (regs->epc == pc) && fp_is_valid(frame->ra, sp)) { ++ /* We hit function where ra is not saved on the stack */ + fp = frame->ra; + pc = regs->ra; + } else { +diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c +index 6cf89314209a6..9e2c9027e986a 100644 +--- a/arch/s390/boot/startup.c ++++ b/arch/s390/boot/startup.c +@@ -32,7 +32,6 @@ unsigned long __bootdata_preserved(max_mappable); + unsigned long __bootdata(ident_map_size); + + u64 __bootdata_preserved(stfle_fac_list[16]); +-u64 __bootdata_preserved(alt_stfle_fac_list[16]); + struct oldmem_data __bootdata_preserved(oldmem_data); + + struct machine_info machine; +diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h +index 621f23d5ae30a..77e479d44f1e3 100644 +--- a/arch/s390/include/asm/ftrace.h ++++ b/arch/s390/include/asm/ftrace.h +@@ -8,12 +8,8 @@ + + #ifndef __ASSEMBLY__ + +-#ifdef CONFIG_CC_IS_CLANG +-/* https://llvm.org/pr41424 */ +-#define ftrace_return_address(n) 0UL +-#else +-#define ftrace_return_address(n) __builtin_return_address(n) +-#endif ++unsigned long return_address(unsigned int n); ++#define ftrace_return_address(n) return_address(n) + + void ftrace_caller(void); + +diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h +index db9982f0e8cd0..bbbdc5abe2b2c 100644 +--- a/arch/s390/include/asm/processor.h ++++ b/arch/s390/include/asm/processor.h +@@ -98,6 +98,7 @@ void cpu_detect_mhz_feature(void); + + extern const struct seq_operations cpuinfo_op; + extern void execve_tail(void); ++unsigned long vdso_text_size(void); + unsigned long vdso_size(void); + + /* +diff --git a/arch/s390/include/asm/stacktrace.h b/arch/s390/include/asm/stacktrace.h +index 433fde85b14ea..85b6738b826af 100644 +--- a/arch/s390/include/asm/stacktrace.h ++++ b/arch/s390/include/asm/stacktrace.h +@@ -2,6 +2,7 @@ + #ifndef _ASM_S390_STACKTRACE_H + #define _ASM_S390_STACKTRACE_H + ++#include <linux/stacktrace.h> + #include <linux/uaccess.h> + #include <linux/ptrace.h> + +@@ -12,6 +13,17 @@ struct stack_frame_user { + unsigned long empty2[4]; + }; + ++struct stack_frame_vdso_wrapper { ++ struct stack_frame_user sf; ++ unsigned long return_address; ++}; ++ ++struct perf_callchain_entry_ctx; ++ ++void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *cookie, ++ struct perf_callchain_entry_ctx *entry, ++ const struct pt_regs *regs, bool perf); ++ + enum stack_type { + STACK_TYPE_UNKNOWN, + STACK_TYPE_TASK, +diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile +index fa029d0dc28ff..db2d9ba5a86d2 100644 +--- a/arch/s390/kernel/Makefile ++++ b/arch/s390/kernel/Makefile +@@ -11,6 +11,8 @@ CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) + # Do not trace early setup code + CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE) + CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE) ++CFLAGS_REMOVE_stacktrace.o = $(CC_FLAGS_FTRACE) ++CFLAGS_REMOVE_unwind_bc.o = $(CC_FLAGS_FTRACE) + + endif + +diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c +index fa5f6885c74aa..2f65bca2f3f1c 100644 +--- a/arch/s390/kernel/asm-offsets.c ++++ b/arch/s390/kernel/asm-offsets.c +@@ -66,6 +66,11 @@ int main(void) + OFFSET(__SF_SIE_CONTROL_PHYS, stack_frame, sie_control_block_phys); + DEFINE(STACK_FRAME_OVERHEAD, sizeof(struct stack_frame)); + BLANK(); ++ OFFSET(__SFUSER_BACKCHAIN, stack_frame_user, back_chain); ++ DEFINE(STACK_FRAME_USER_OVERHEAD, sizeof(struct stack_frame_user)); ++ OFFSET(__SFVDSO_RETURN_ADDRESS, stack_frame_vdso_wrapper, return_address); ++ DEFINE(STACK_FRAME_VDSO_OVERHEAD, sizeof(struct stack_frame_vdso_wrapper)); ++ BLANK(); + /* idle data offsets */ + OFFSET(__CLOCK_IDLE_ENTER, s390_idle_data, clock_idle_enter); + OFFSET(__TIMER_IDLE_ENTER, s390_idle_data, timer_idle_enter); +diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c +index 1486350a41775..469e8d3fbfbf3 100644 +--- a/arch/s390/kernel/ipl.c ++++ b/arch/s390/kernel/ipl.c +@@ -962,8 +962,8 @@ static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj, + scpdata_len += padding; + } + +- reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len; +- reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len; ++ reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN + scpdata_len; ++ reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN + scpdata_len; + reipl_block_nvme->nvme.scp_data_len = scpdata_len; + + return count; +@@ -1858,9 +1858,9 @@ static int __init dump_nvme_init(void) + } + dump_block_nvme->hdr.len = IPL_BP_NVME_LEN; + dump_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION; +- dump_block_nvme->fcp.len = IPL_BP0_NVME_LEN; +- dump_block_nvme->fcp.pbt = IPL_PBT_NVME; +- dump_block_nvme->fcp.opt = IPL_PB0_NVME_OPT_DUMP; ++ dump_block_nvme->nvme.len = IPL_BP0_NVME_LEN; ++ dump_block_nvme->nvme.pbt = IPL_PBT_NVME; ++ dump_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_DUMP; + dump_capabilities |= DUMP_TYPE_NVME; + return 0; + } +diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c +index dfa77da2fd2ec..5fff629b1a898 100644 +--- a/arch/s390/kernel/perf_event.c ++++ b/arch/s390/kernel/perf_event.c +@@ -218,39 +218,7 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { +- struct stack_frame_user __user *sf; +- unsigned long ip, sp; +- bool first = true; +- +- if (is_compat_task()) +- return; +- perf_callchain_store(entry, instruction_pointer(regs)); +- sf = (void __user *)user_stack_pointer(regs); +- pagefault_disable(); +- while (entry->nr < entry->max_stack) { +- if (__get_user(sp, &sf->back_chain)) +- break; +- if (__get_user(ip, &sf->gprs[8])) +- break; +- if (ip & 0x1) { +- /* +- * If the instruction address is invalid, and this +- * is the first stack frame, assume r14 has not +- * been written to the stack yet. Otherwise exit. +- */ +- if (first && !(regs->gprs[14] & 0x1)) +- ip = regs->gprs[14]; +- else +- break; +- } +- perf_callchain_store(entry, ip); +- /* Sanity check: ABI requires SP to be aligned 8 bytes. */ +- if (!sp || sp & 0x7) +- break; +- sf = (void __user *)sp; +- first = false; +- } +- pagefault_enable(); ++ arch_stack_walk_user_common(NULL, NULL, entry, regs, true); + } + + /* Perf definitions for PMU event attributes in sysfs */ +diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c +index 24ed33f044ec3..7ecd27c62d564 100644 +--- a/arch/s390/kernel/setup.c ++++ b/arch/s390/kernel/setup.c +@@ -155,7 +155,7 @@ unsigned int __bootdata_preserved(zlib_dfltcc_support); + EXPORT_SYMBOL(zlib_dfltcc_support); + u64 __bootdata_preserved(stfle_fac_list[16]); + EXPORT_SYMBOL(stfle_fac_list); +-u64 __bootdata_preserved(alt_stfle_fac_list[16]); ++u64 alt_stfle_fac_list[16]; + struct oldmem_data __bootdata_preserved(oldmem_data); + + unsigned long VMALLOC_START; +diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c +index 94f440e383031..640363b2a1059 100644 +--- a/arch/s390/kernel/stacktrace.c ++++ b/arch/s390/kernel/stacktrace.c +@@ -5,6 +5,7 @@ + * Copyright IBM Corp. 2006 + */ + ++#include <linux/perf_event.h> + #include <linux/stacktrace.h> + #include <linux/uaccess.h> + #include <linux/compat.h> +@@ -62,42 +63,121 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry, + return 0; + } + +-void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie, +- const struct pt_regs *regs) ++static inline bool store_ip(stack_trace_consume_fn consume_entry, void *cookie, ++ struct perf_callchain_entry_ctx *entry, bool perf, ++ unsigned long ip) ++{ ++#ifdef CONFIG_PERF_EVENTS ++ if (perf) { ++ if (perf_callchain_store(entry, ip)) ++ return false; ++ return true; ++ } ++#endif ++ return consume_entry(cookie, ip); ++} ++ ++static inline bool ip_invalid(unsigned long ip) ++{ ++ /* ++ * Perform some basic checks if an instruction address taken ++ * from unreliable source is invalid. ++ */ ++ if (ip & 1) ++ return true; ++ if (ip < mmap_min_addr) ++ return true; ++ if (ip >= current->mm->context.asce_limit) ++ return true; ++ return false; ++} ++ ++static inline bool ip_within_vdso(unsigned long ip) + { ++ return in_range(ip, current->mm->context.vdso_base, vdso_text_size()); ++} ++ ++void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *cookie, ++ struct perf_callchain_entry_ctx *entry, ++ const struct pt_regs *regs, bool perf) ++{ ++ struct stack_frame_vdso_wrapper __user *sf_vdso; + struct stack_frame_user __user *sf; + unsigned long ip, sp; + bool first = true; + + if (is_compat_task()) + return; +- if (!consume_entry(cookie, instruction_pointer(regs))) ++ if (!current->mm) ++ return; ++ ip = instruction_pointer(regs); ++ if (!store_ip(consume_entry, cookie, entry, perf, ip)) + return; + sf = (void __user *)user_stack_pointer(regs); + pagefault_disable(); + while (1) { + if (__get_user(sp, &sf->back_chain)) + break; +- if (__get_user(ip, &sf->gprs[8])) ++ /* ++ * VDSO entry code has a non-standard stack frame layout. ++ * See VDSO user wrapper code for details. ++ */ ++ if (!sp && ip_within_vdso(ip)) { ++ sf_vdso = (void __user *)sf; ++ if (__get_user(ip, &sf_vdso->return_address)) ++ break; ++ sp = (unsigned long)sf + STACK_FRAME_VDSO_OVERHEAD; ++ sf = (void __user *)sp; ++ if (__get_user(sp, &sf->back_chain)) ++ break; ++ } else { ++ sf = (void __user *)sp; ++ if (__get_user(ip, &sf->gprs[8])) ++ break; ++ } ++ /* Sanity check: ABI requires SP to be 8 byte aligned. */ ++ if (sp & 0x7) + break; +- if (ip & 0x1) { ++ if (ip_invalid(ip)) { + /* + * If the instruction address is invalid, and this + * is the first stack frame, assume r14 has not + * been written to the stack yet. Otherwise exit. + */ +- if (first && !(regs->gprs[14] & 0x1)) +- ip = regs->gprs[14]; +- else ++ if (!first) ++ break; ++ ip = regs->gprs[14]; ++ if (ip_invalid(ip)) + break; + } +- if (!consume_entry(cookie, ip)) +- break; +- /* Sanity check: ABI requires SP to be aligned 8 bytes. */ +- if (!sp || sp & 0x7) +- break; +- sf = (void __user *)sp; ++ if (!store_ip(consume_entry, cookie, entry, perf, ip)) ++ return; + first = false; + } + pagefault_enable(); + } ++ ++void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie, ++ const struct pt_regs *regs) ++{ ++ arch_stack_walk_user_common(consume_entry, cookie, NULL, regs, false); ++} ++ ++unsigned long return_address(unsigned int n) ++{ ++ struct unwind_state state; ++ unsigned long addr; ++ ++ /* Increment to skip current stack entry */ ++ n++; ++ ++ unwind_for_each_frame(&state, NULL, NULL, 0) { ++ addr = unwind_get_return_address(&state); ++ if (!addr) ++ break; ++ if (!n--) ++ return addr; ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(return_address); +diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c +index a45b3a4c91db0..2f967ac2b8e3e 100644 +--- a/arch/s390/kernel/vdso.c ++++ b/arch/s390/kernel/vdso.c +@@ -210,17 +210,22 @@ static unsigned long vdso_addr(unsigned long start, unsigned long len) + return addr; + } + +-unsigned long vdso_size(void) ++unsigned long vdso_text_size(void) + { +- unsigned long size = VVAR_NR_PAGES * PAGE_SIZE; ++ unsigned long size; + + if (is_compat_task()) +- size += vdso32_end - vdso32_start; ++ size = vdso32_end - vdso32_start; + else +- size += vdso64_end - vdso64_start; ++ size = vdso64_end - vdso64_start; + return PAGE_ALIGN(size); + } + ++unsigned long vdso_size(void) ++{ ++ return vdso_text_size() + VVAR_NR_PAGES * PAGE_SIZE; ++} ++ + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) + { + unsigned long addr = VDSO_BASE; +diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile +index b12a274cbb473..4800d80decee6 100644 +--- a/arch/s390/kernel/vdso32/Makefile ++++ b/arch/s390/kernel/vdso32/Makefile +@@ -19,8 +19,10 @@ KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS)) + KBUILD_AFLAGS_32 += -m31 -s + + KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS)) ++KBUILD_CFLAGS_32 := $(filter-out -mpacked-stack,$(KBUILD_CFLAGS)) + KBUILD_CFLAGS_32 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_32)) +-KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin ++KBUILD_CFLAGS_32 := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_32)) ++KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin -fasynchronous-unwind-tables + + LDFLAGS_vdso32.so.dbg += -shared -soname=linux-vdso32.so.1 \ + --hash-style=both --build-id=sha1 -melf_s390 -T +diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile +index ef98327260972..2f2e4e997030c 100644 +--- a/arch/s390/kernel/vdso64/Makefile ++++ b/arch/s390/kernel/vdso64/Makefile +@@ -24,9 +24,11 @@ KBUILD_AFLAGS_64 := $(filter-out -m64,$(KBUILD_AFLAGS)) + KBUILD_AFLAGS_64 += -m64 + + KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS)) ++KBUILD_CFLAGS_64 := $(filter-out -mpacked-stack,$(KBUILD_CFLAGS_64)) + KBUILD_CFLAGS_64 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_64)) + KBUILD_CFLAGS_64 := $(filter-out -munaligned-symbols,$(KBUILD_CFLAGS_64)) +-KBUILD_CFLAGS_64 += -m64 -fPIC -fno-common -fno-builtin ++KBUILD_CFLAGS_64 := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_64)) ++KBUILD_CFLAGS_64 += -m64 -fPIC -fno-common -fno-builtin -fasynchronous-unwind-tables + ldflags-y := -shared -soname=linux-vdso64.so.1 \ + --hash-style=both --build-id=sha1 -T + +diff --git a/arch/s390/kernel/vdso64/vdso_user_wrapper.S b/arch/s390/kernel/vdso64/vdso_user_wrapper.S +index 85247ef5a41b8..e26e68675c08d 100644 +--- a/arch/s390/kernel/vdso64/vdso_user_wrapper.S ++++ b/arch/s390/kernel/vdso64/vdso_user_wrapper.S +@@ -6,8 +6,6 @@ + #include <asm/dwarf.h> + #include <asm/ptrace.h> + +-#define WRAPPER_FRAME_SIZE (STACK_FRAME_OVERHEAD+8) +- + /* + * Older glibc version called vdso without allocating a stackframe. This wrapper + * is just used to allocate a stackframe. See +@@ -20,16 +18,17 @@ + __ALIGN + __kernel_\func: + CFI_STARTPROC +- aghi %r15,-WRAPPER_FRAME_SIZE +- CFI_DEF_CFA_OFFSET (STACK_FRAME_OVERHEAD + WRAPPER_FRAME_SIZE) +- CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD +- stg %r14,STACK_FRAME_OVERHEAD(%r15) +- CFI_REL_OFFSET 14, STACK_FRAME_OVERHEAD ++ aghi %r15,-STACK_FRAME_VDSO_OVERHEAD ++ CFI_DEF_CFA_OFFSET (STACK_FRAME_USER_OVERHEAD + STACK_FRAME_VDSO_OVERHEAD) ++ CFI_VAL_OFFSET 15,-STACK_FRAME_USER_OVERHEAD ++ stg %r14,__SFVDSO_RETURN_ADDRESS(%r15) ++ CFI_REL_OFFSET 14,__SFVDSO_RETURN_ADDRESS ++ xc __SFUSER_BACKCHAIN(8,%r15),__SFUSER_BACKCHAIN(%r15) + brasl %r14,__s390_vdso_\func +- lg %r14,STACK_FRAME_OVERHEAD(%r15) ++ lg %r14,__SFVDSO_RETURN_ADDRESS(%r15) + CFI_RESTORE 14 +- aghi %r15,WRAPPER_FRAME_SIZE +- CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD ++ aghi %r15,STACK_FRAME_VDSO_OVERHEAD ++ CFI_DEF_CFA_OFFSET STACK_FRAME_USER_OVERHEAD + CFI_RESTORE 15 + br %r14 + CFI_ENDPROC +diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c +index ffc5cb92fa367..d82bc3fdb86e7 100644 +--- a/arch/um/drivers/line.c ++++ b/arch/um/drivers/line.c +@@ -676,24 +676,26 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port, + goto cleanup; + } + +- *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), +- .fd = fd, ++ *winch = ((struct winch) { .fd = fd, + .tty_fd = tty_fd, + .pid = pid, + .port = port, + .stack = stack }); + ++ spin_lock(&winch_handler_lock); ++ list_add(&winch->list, &winch_handlers); ++ spin_unlock(&winch_handler_lock); ++ + if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, + IRQF_SHARED, "winch", winch) < 0) { + printk(KERN_ERR "register_winch_irq - failed to register " + "IRQ\n"); ++ spin_lock(&winch_handler_lock); ++ list_del(&winch->list); ++ spin_unlock(&winch_handler_lock); + goto out_free; + } + +- spin_lock(&winch_handler_lock); +- list_add(&winch->list, &winch_handlers); +- spin_unlock(&winch_handler_lock); +- + return; + + out_free: +diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c +index 63fc062add708..ef805eaa9e013 100644 +--- a/arch/um/drivers/ubd_kern.c ++++ b/arch/um/drivers/ubd_kern.c +@@ -1092,7 +1092,7 @@ static int __init ubd_init(void) + + if (irq_req_buffer == NULL) { + printk(KERN_ERR "Failed to initialize ubd buffering\n"); +- return -1; ++ return -ENOMEM; + } + io_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE, + sizeof(struct io_thread_req *), +@@ -1103,7 +1103,7 @@ static int __init ubd_init(void) + + if (io_req_buffer == NULL) { + printk(KERN_ERR "Failed to initialize ubd buffering\n"); +- return -1; ++ return -ENOMEM; + } + platform_driver_register(&ubd_driver); + mutex_lock(&ubd_lock); +diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c +index dc2feae789cbb..63e5f108a6b95 100644 +--- a/arch/um/drivers/vector_kern.c ++++ b/arch/um/drivers/vector_kern.c +@@ -141,7 +141,7 @@ static bool get_bpf_flash(struct arglist *def) + + if (allow != NULL) { + if (kstrtoul(allow, 10, &result) == 0) +- return (allow > 0); ++ return result > 0; + } + return false; + } +diff --git a/arch/um/include/asm/kasan.h b/arch/um/include/asm/kasan.h +index 0d6547f4ec85c..f97bb1f7b8514 100644 +--- a/arch/um/include/asm/kasan.h ++++ b/arch/um/include/asm/kasan.h +@@ -24,7 +24,6 @@ + + #ifdef CONFIG_KASAN + void kasan_init(void); +-void kasan_map_memory(void *start, unsigned long len); + extern int kasan_um_is_ready; + + #ifdef CONFIG_STATIC_LINK +diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h +index a7555e43ed14a..f2923c767bb9a 100644 +--- a/arch/um/include/asm/mmu.h ++++ b/arch/um/include/asm/mmu.h +@@ -14,8 +14,6 @@ typedef struct mm_context { + struct uml_arch_mm_context arch; + } mm_context_t; + +-extern void __switch_mm(struct mm_id * mm_idp); +- + /* Avoid tangled inclusion with asm/ldt.h */ + extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm); + extern void free_ldt(struct mm_context *mm); +diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h +index 6c3779541845b..5a7c05275aa74 100644 +--- a/arch/um/include/asm/processor-generic.h ++++ b/arch/um/include/asm/processor-generic.h +@@ -94,7 +94,6 @@ extern struct cpuinfo_um boot_cpu_data; + #define current_cpu_data boot_cpu_data + #define cache_line_size() (boot_cpu_data.cache_alignment) + +-extern unsigned long get_thread_reg(int reg, jmp_buf *buf); + #define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf) + extern unsigned long __get_wchan(struct task_struct *p); + +diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h +index 789b83013f355..af8cdfc75897e 100644 +--- a/arch/um/include/shared/kern_util.h ++++ b/arch/um/include/shared/kern_util.h +@@ -66,4 +66,6 @@ extern void fatal_sigsegv(void) __attribute__ ((noreturn)); + + void um_idle_sleep(void); + ++void kasan_map_memory(void *start, size_t len); ++ + #endif +diff --git a/arch/um/include/shared/skas/mm_id.h b/arch/um/include/shared/skas/mm_id.h +index e82e203f5f419..92dbf727e3842 100644 +--- a/arch/um/include/shared/skas/mm_id.h ++++ b/arch/um/include/shared/skas/mm_id.h +@@ -15,4 +15,6 @@ struct mm_id { + int kill; + }; + ++void __switch_mm(struct mm_id *mm_idp); ++ + #endif +diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c +index 8530b2e086049..c6c9495b14321 100644 +--- a/arch/um/os-Linux/mem.c ++++ b/arch/um/os-Linux/mem.c +@@ -15,6 +15,7 @@ + #include <sys/vfs.h> + #include <linux/magic.h> + #include <init.h> ++#include <kern_util.h> + #include <os.h> + + /* +diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug +index c5d614d28a759..74777a97e394a 100644 +--- a/arch/x86/Kconfig.debug ++++ b/arch/x86/Kconfig.debug +@@ -248,6 +248,7 @@ config UNWINDER_ORC + + config UNWINDER_FRAME_POINTER + bool "Frame pointer unwinder" ++ select ARCH_WANT_FRAME_POINTERS + select FRAME_POINTER + help + This option enables the frame pointer unwinder for unwinding kernel +@@ -271,7 +272,3 @@ config UNWINDER_GUESS + overhead. + + endchoice +- +-config FRAME_POINTER +- depends on !UNWINDER_ORC && !UNWINDER_GUESS +- bool +diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h +index b77bbb67e77b0..ce5111cec36e2 100644 +--- a/arch/x86/include/asm/percpu.h ++++ b/arch/x86/include/asm/percpu.h +@@ -59,36 +59,30 @@ + #define __force_percpu_prefix "%%"__stringify(__percpu_seg)":" + #define __my_cpu_offset this_cpu_read(this_cpu_off) + +-#ifdef CONFIG_USE_X86_SEG_SUPPORT +-/* +- * Efficient implementation for cases in which the compiler supports +- * named address spaces. Allows the compiler to perform additional +- * optimizations that can save more instructions. +- */ +-#define arch_raw_cpu_ptr(ptr) \ +-({ \ +- unsigned long tcp_ptr__; \ +- tcp_ptr__ = __raw_cpu_read(, this_cpu_off); \ +- \ +- tcp_ptr__ += (__force unsigned long)(ptr); \ +- (typeof(*(ptr)) __kernel __force *)tcp_ptr__; \ +-}) +-#else /* CONFIG_USE_X86_SEG_SUPPORT */ ++#ifdef CONFIG_X86_64 ++#define __raw_my_cpu_offset raw_cpu_read_8(this_cpu_off); ++#else ++#define __raw_my_cpu_offset raw_cpu_read_4(this_cpu_off); ++#endif ++ + /* + * Compared to the generic __my_cpu_offset version, the following + * saves one instruction and avoids clobbering a temp register. ++ * ++ * arch_raw_cpu_ptr should not be used in 32-bit VDSO for a 64-bit ++ * kernel, because games are played with CONFIG_X86_64 there and ++ * sizeof(this_cpu_off) becames 4. + */ +-#define arch_raw_cpu_ptr(ptr) \ ++#ifndef BUILD_VDSO32_64 ++#define arch_raw_cpu_ptr(_ptr) \ + ({ \ +- unsigned long tcp_ptr__; \ +- asm ("mov " __percpu_arg(1) ", %0" \ +- : "=r" (tcp_ptr__) \ +- : "m" (__my_cpu_var(this_cpu_off))); \ +- \ +- tcp_ptr__ += (unsigned long)(ptr); \ +- (typeof(*(ptr)) __kernel __force *)tcp_ptr__; \ ++ unsigned long tcp_ptr__ = __raw_my_cpu_offset; \ ++ tcp_ptr__ += (__force unsigned long)(_ptr); \ ++ (typeof(*(_ptr)) __kernel __force *)tcp_ptr__; \ + }) +-#endif /* CONFIG_USE_X86_SEG_SUPPORT */ ++#else ++#define arch_raw_cpu_ptr(_ptr) ({ BUILD_BUG(); (typeof(_ptr))0; }) ++#endif + + #define PER_CPU_VAR(var) %__percpu_seg:(var)__percpu_rel + +diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c +index 185738c727661..29cd0543fc2fb 100644 +--- a/arch/x86/kernel/apic/vector.c ++++ b/arch/x86/kernel/apic/vector.c +@@ -1036,7 +1036,8 @@ static void __vector_schedule_cleanup(struct apic_chip_data *apicd) + add_timer_on(&cl->timer, cpu); + } + } else { +- apicd->prev_vector = 0; ++ pr_warn("IRQ %u schedule cleanup for offline CPU %u\n", apicd->irq, cpu); ++ free_moved_vector(apicd); + } + raw_spin_unlock(&vector_lock); + } +@@ -1073,6 +1074,7 @@ void irq_complete_move(struct irq_cfg *cfg) + */ + void irq_force_complete_move(struct irq_desc *desc) + { ++ unsigned int cpu = smp_processor_id(); + struct apic_chip_data *apicd; + struct irq_data *irqd; + unsigned int vector; +@@ -1097,10 +1099,11 @@ void irq_force_complete_move(struct irq_desc *desc) + goto unlock; + + /* +- * If prev_vector is empty, no action required. ++ * If prev_vector is empty or the descriptor is neither currently ++ * nor previously on the outgoing CPU no action required. + */ + vector = apicd->prev_vector; +- if (!vector) ++ if (!vector || (apicd->cpu != cpu && apicd->prev_cpu != cpu)) + goto unlock; + + /* +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 605c26c009c8a..ae987a26f26e4 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1589,6 +1589,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) + if (have_cpuid_p()) { + cpu_detect(c); + get_cpu_vendor(c); ++ intel_unlock_cpuid_leafs(c); + get_cpu_cap(c); + setup_force_cpu_cap(X86_FEATURE_CPUID); + get_cpu_address_sizes(c); +@@ -1748,7 +1749,7 @@ static void generic_identify(struct cpuinfo_x86 *c) + cpu_detect(c); + + get_cpu_vendor(c); +- ++ intel_unlock_cpuid_leafs(c); + get_cpu_cap(c); + + get_cpu_address_sizes(c); +diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h +index ea9e07d57c8dd..1beccefbaff9a 100644 +--- a/arch/x86/kernel/cpu/cpu.h ++++ b/arch/x86/kernel/cpu/cpu.h +@@ -61,9 +61,11 @@ extern __ro_after_init enum tsx_ctrl_states tsx_ctrl_state; + + extern void __init tsx_init(void); + void tsx_ap_init(void); ++void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c); + #else + static inline void tsx_init(void) { } + static inline void tsx_ap_init(void) { } ++static inline void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c) { } + #endif /* CONFIG_CPU_SUP_INTEL */ + + extern void init_spectral_chicken(struct cpuinfo_x86 *c); +diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c +index be30d7fa2e66b..93efd9edc7242 100644 +--- a/arch/x86/kernel/cpu/intel.c ++++ b/arch/x86/kernel/cpu/intel.c +@@ -268,19 +268,26 @@ static void detect_tme_early(struct cpuinfo_x86 *c) + c->x86_phys_bits -= keyid_bits; + } + ++void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c) ++{ ++ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) ++ return; ++ ++ if (c->x86 < 6 || (c->x86 == 6 && c->x86_model < 0xd)) ++ return; ++ ++ /* ++ * The BIOS can have limited CPUID to leaf 2, which breaks feature ++ * enumeration. Unlock it and update the maximum leaf info. ++ */ ++ if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0) ++ c->cpuid_level = cpuid_eax(0); ++} ++ + static void early_init_intel(struct cpuinfo_x86 *c) + { + u64 misc_enable; + +- /* Unmask CPUID levels if masked: */ +- if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) { +- if (msr_clear_bit(MSR_IA32_MISC_ENABLE, +- MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0) { +- c->cpuid_level = cpuid_eax(0); +- get_cpu_cap(c); +- } +- } +- + if ((c->x86 == 0xf && c->x86_model >= 0x03) || + (c->x86 == 0x6 && c->x86_model >= 0x0e)) + set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); +diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c +index d17c9b71eb4a2..621a151ccf7d0 100644 +--- a/arch/x86/kernel/cpu/topology.c ++++ b/arch/x86/kernel/cpu/topology.c +@@ -128,6 +128,9 @@ static void topo_set_cpuids(unsigned int cpu, u32 apic_id, u32 acpi_id) + + static __init bool check_for_real_bsp(u32 apic_id) + { ++ bool is_bsp = false, has_apic_base = boot_cpu_data.x86 >= 6; ++ u64 msr; ++ + /* + * There is no real good way to detect whether this a kdump() + * kernel, but except on the Voyager SMP monstrosity which is not +@@ -144,17 +147,61 @@ static __init bool check_for_real_bsp(u32 apic_id) + if (topo_info.real_bsp_apic_id != BAD_APICID) + return false; + ++ /* ++ * Check whether the enumeration order is broken by evaluating the ++ * BSP bit in the APICBASE MSR. If the CPU does not have the ++ * APICBASE MSR then the BSP detection is not possible and the ++ * kernel must rely on the firmware enumeration order. ++ */ ++ if (has_apic_base) { ++ rdmsrl(MSR_IA32_APICBASE, msr); ++ is_bsp = !!(msr & MSR_IA32_APICBASE_BSP); ++ } ++ + if (apic_id == topo_info.boot_cpu_apic_id) { +- topo_info.real_bsp_apic_id = apic_id; +- return false; ++ /* ++ * If the boot CPU has the APIC BSP bit set then the ++ * firmware enumeration is agreeing. If the CPU does not ++ * have the APICBASE MSR then the only choice is to trust ++ * the enumeration order. ++ */ ++ if (is_bsp || !has_apic_base) { ++ topo_info.real_bsp_apic_id = apic_id; ++ return false; ++ } ++ /* ++ * If the boot APIC is enumerated first, but the APICBASE ++ * MSR does not have the BSP bit set, then there is no way ++ * to discover the real BSP here. Assume a crash kernel and ++ * limit the number of CPUs to 1 as an INIT to the real BSP ++ * would reset the machine. ++ */ ++ pr_warn("Enumerated BSP APIC %x is not marked in APICBASE MSR\n", apic_id); ++ pr_warn("Assuming crash kernel. Limiting to one CPU to prevent machine INIT\n"); ++ set_nr_cpu_ids(1); ++ goto fwbug; + } + +- pr_warn("Boot CPU APIC ID not the first enumerated APIC ID: %x > %x\n", ++ pr_warn("Boot CPU APIC ID not the first enumerated APIC ID: %x != %x\n", + topo_info.boot_cpu_apic_id, apic_id); ++ ++ if (is_bsp) { ++ /* ++ * The boot CPU has the APIC BSP bit set. Use it and complain ++ * about the broken firmware enumeration. ++ */ ++ topo_info.real_bsp_apic_id = topo_info.boot_cpu_apic_id; ++ goto fwbug; ++ } ++ + pr_warn("Crash kernel detected. Disabling real BSP to prevent machine INIT\n"); + + topo_info.real_bsp_apic_id = apic_id; + return true; ++ ++fwbug: ++ pr_warn(FW_BUG "APIC enumeration order not specification compliant\n"); ++ return false; + } + + static unsigned int topo_unit_count(u32 lvlid, enum x86_topology_domains at_level, +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index 77352a4abd87f..b1002b79886ab 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -1232,9 +1232,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) + entry->eax = entry->ebx = entry->ecx = 0; + break; + case 0x80000008: { +- unsigned g_phys_as = (entry->eax >> 16) & 0xff; +- unsigned virt_as = max((entry->eax >> 8) & 0xff, 48U); +- unsigned phys_as = entry->eax & 0xff; ++ unsigned int virt_as = max((entry->eax >> 8) & 0xff, 48U); ++ unsigned int phys_as; + + /* + * If TDP (NPT) is disabled use the adjusted host MAXPHYADDR as +@@ -1242,16 +1241,16 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) + * reductions in MAXPHYADDR for memory encryption affect shadow + * paging, too. + * +- * If TDP is enabled but an explicit guest MAXPHYADDR is not +- * provided, use the raw bare metal MAXPHYADDR as reductions to +- * the HPAs do not affect GPAs. ++ * If TDP is enabled, use the raw bare metal MAXPHYADDR as ++ * reductions to the HPAs do not affect GPAs. + */ +- if (!tdp_enabled) +- g_phys_as = boot_cpu_data.x86_phys_bits; +- else if (!g_phys_as) +- g_phys_as = phys_as; ++ if (!tdp_enabled) { ++ phys_as = boot_cpu_data.x86_phys_bits; ++ } else { ++ phys_as = entry->eax & 0xff; ++ } + +- entry->eax = g_phys_as | (virt_as << 8); ++ entry->eax = phys_as | (virt_as << 8); + entry->ecx &= ~(GENMASK(31, 16) | GENMASK(11, 8)); + entry->edx = 0; + cpuid_entry_override(entry, CPUID_8000_0008_EBX); +diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c +index 0cc9520666efb..39255f0eb14df 100644 +--- a/arch/x86/pci/mmconfig-shared.c ++++ b/arch/x86/pci/mmconfig-shared.c +@@ -518,7 +518,34 @@ static bool __ref pci_mmcfg_reserved(struct device *dev, + { + struct resource *conflict; + +- if (!early && !acpi_disabled) { ++ if (early) { ++ ++ /* ++ * Don't try to do this check unless configuration type 1 ++ * is available. How about type 2? ++ */ ++ ++ /* ++ * 946f2ee5c731 ("Check that MCFG points to an e820 ++ * reserved area") added this E820 check in 2006 to work ++ * around BIOS defects. ++ * ++ * Per PCI Firmware r3.3, sec 4.1.2, ECAM space must be ++ * reserved by a PNP0C02 resource, but it need not be ++ * mentioned in E820. Before the ACPI interpreter is ++ * available, we can't check for PNP0C02 resources, so ++ * there's no reliable way to verify the region in this ++ * early check. Keep it only for the old machines that ++ * motivated 946f2ee5c731. ++ */ ++ if (dmi_get_bios_year() < 2016 && raw_pci_ops) ++ return is_mmconf_reserved(e820__mapped_all, cfg, dev, ++ "E820 entry"); ++ ++ return true; ++ } ++ ++ if (!acpi_disabled) { + if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, + "ACPI motherboard resource")) + return true; +@@ -551,16 +578,7 @@ static bool __ref pci_mmcfg_reserved(struct device *dev, + * For MCFG information constructed from hotpluggable host bridge's + * _CBA method, just assume it's reserved. + */ +- if (pci_mmcfg_running_state) +- return true; +- +- /* Don't try to do this check unless configuration +- type 1 is available. how about type 2 ?*/ +- if (raw_pci_ops) +- return is_mmconf_reserved(e820__mapped_all, cfg, dev, +- "E820 entry"); +- +- return false; ++ return pci_mmcfg_running_state; + } + + static void __init pci_mmcfg_reject_broken(int early) +diff --git a/arch/x86/um/shared/sysdep/archsetjmp.h b/arch/x86/um/shared/sysdep/archsetjmp.h +index 166cedbab9266..8c81d1a604a94 100644 +--- a/arch/x86/um/shared/sysdep/archsetjmp.h ++++ b/arch/x86/um/shared/sysdep/archsetjmp.h +@@ -1,6 +1,13 @@ + /* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef __X86_UM_SYSDEP_ARCHSETJMP_H ++#define __X86_UM_SYSDEP_ARCHSETJMP_H ++ + #ifdef __i386__ + #include "archsetjmp_32.h" + #else + #include "archsetjmp_64.h" + #endif ++ ++unsigned long get_thread_reg(int reg, jmp_buf *buf); ++ ++#endif /* __X86_UM_SYSDEP_ARCHSETJMP_H */ +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index a01ca255b0c64..b88722dfc4f86 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -382,3 +382,36 @@ void __init xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns) + + memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns)); + } ++ ++#ifdef CONFIG_XEN_UNPOPULATED_ALLOC ++int __init arch_xen_unpopulated_init(struct resource **res) ++{ ++ unsigned int i; ++ ++ if (!xen_domain()) ++ return -ENODEV; ++ ++ /* Must be set strictly before calling xen_free_unpopulated_pages(). */ ++ *res = &iomem_resource; ++ ++ /* ++ * Initialize with pages from the extra memory regions (see ++ * arch/x86/xen/setup.c). ++ */ ++ for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { ++ unsigned int j; ++ ++ for (j = 0; j < xen_extra_mem[i].n_pfns; j++) { ++ struct page *pg = ++ pfn_to_page(xen_extra_mem[i].start_pfn + j); ++ ++ xen_free_unpopulated_pages(1, &pg); ++ } ++ ++ /* Zero so region is not also added to the balloon driver. */ ++ xen_extra_mem[i].n_pfns = 0; ++ } ++ ++ return 0; ++} ++#endif +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index 059467086b131..96af8224992e6 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -323,6 +323,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk, + blkg->q = disk->queue; + INIT_LIST_HEAD(&blkg->q_node); + blkg->blkcg = blkcg; ++ blkg->iostat.blkg = blkg; + #ifdef CONFIG_BLK_CGROUP_PUNT_BIO + spin_lock_init(&blkg->async_bio_lock); + bio_list_init(&blkg->async_bios); +@@ -619,12 +620,45 @@ static void blkg_destroy_all(struct gendisk *disk) + spin_unlock_irq(&q->queue_lock); + } + ++static void blkg_iostat_set(struct blkg_iostat *dst, struct blkg_iostat *src) ++{ ++ int i; ++ ++ for (i = 0; i < BLKG_IOSTAT_NR; i++) { ++ dst->bytes[i] = src->bytes[i]; ++ dst->ios[i] = src->ios[i]; ++ } ++} ++ ++static void __blkg_clear_stat(struct blkg_iostat_set *bis) ++{ ++ struct blkg_iostat cur = {0}; ++ unsigned long flags; ++ ++ flags = u64_stats_update_begin_irqsave(&bis->sync); ++ blkg_iostat_set(&bis->cur, &cur); ++ blkg_iostat_set(&bis->last, &cur); ++ u64_stats_update_end_irqrestore(&bis->sync, flags); ++} ++ ++static void blkg_clear_stat(struct blkcg_gq *blkg) ++{ ++ int cpu; ++ ++ for_each_possible_cpu(cpu) { ++ struct blkg_iostat_set *s = per_cpu_ptr(blkg->iostat_cpu, cpu); ++ ++ __blkg_clear_stat(s); ++ } ++ __blkg_clear_stat(&blkg->iostat); ++} ++ + static int blkcg_reset_stats(struct cgroup_subsys_state *css, + struct cftype *cftype, u64 val) + { + struct blkcg *blkcg = css_to_blkcg(css); + struct blkcg_gq *blkg; +- int i, cpu; ++ int i; + + mutex_lock(&blkcg_pol_mutex); + spin_lock_irq(&blkcg->lock); +@@ -635,18 +669,7 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css, + * anyway. If you get hit by a race, retry. + */ + hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) { +- for_each_possible_cpu(cpu) { +- struct blkg_iostat_set *bis = +- per_cpu_ptr(blkg->iostat_cpu, cpu); +- memset(bis, 0, sizeof(*bis)); +- +- /* Re-initialize the cleared blkg_iostat_set */ +- u64_stats_init(&bis->sync); +- bis->blkg = blkg; +- } +- memset(&blkg->iostat, 0, sizeof(blkg->iostat)); +- u64_stats_init(&blkg->iostat.sync); +- ++ blkg_clear_stat(blkg); + for (i = 0; i < BLKCG_MAX_POLS; i++) { + struct blkcg_policy *pol = blkcg_policy[i]; + +@@ -949,16 +972,6 @@ void blkg_conf_exit(struct blkg_conf_ctx *ctx) + } + EXPORT_SYMBOL_GPL(blkg_conf_exit); + +-static void blkg_iostat_set(struct blkg_iostat *dst, struct blkg_iostat *src) +-{ +- int i; +- +- for (i = 0; i < BLKG_IOSTAT_NR; i++) { +- dst->bytes[i] = src->bytes[i]; +- dst->ios[i] = src->ios[i]; +- } +-} +- + static void blkg_iostat_add(struct blkg_iostat *dst, struct blkg_iostat *src) + { + int i; +@@ -1024,7 +1037,19 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu) + struct blkg_iostat cur; + unsigned int seq; + ++ /* ++ * Order assignment of `next_bisc` from `bisc->lnode.next` in ++ * llist_for_each_entry_safe and clearing `bisc->lqueued` for ++ * avoiding to assign `next_bisc` with new next pointer added ++ * in blk_cgroup_bio_start() in case of re-ordering. ++ * ++ * The pair barrier is implied in llist_add() in blk_cgroup_bio_start(). ++ */ ++ smp_mb(); ++ + WRITE_ONCE(bisc->lqueued, false); ++ if (bisc == &blkg->iostat) ++ goto propagate_up; /* propagate up to parent only */ + + /* fetch the current per-cpu values */ + do { +@@ -1034,10 +1059,24 @@ static void __blkcg_rstat_flush(struct blkcg *blkcg, int cpu) + + blkcg_iostat_update(blkg, &cur, &bisc->last); + ++propagate_up: + /* propagate global delta to parent (unless that's root) */ +- if (parent && parent->parent) ++ if (parent && parent->parent) { + blkcg_iostat_update(parent, &blkg->iostat.cur, + &blkg->iostat.last); ++ /* ++ * Queue parent->iostat to its blkcg's lockless ++ * list to propagate up to the grandparent if the ++ * iostat hasn't been queued yet. ++ */ ++ if (!parent->iostat.lqueued) { ++ struct llist_head *plhead; ++ ++ plhead = per_cpu_ptr(parent->blkcg->lhead, cpu); ++ llist_add(&parent->iostat.lnode, plhead); ++ parent->iostat.lqueued = true; ++ } ++ } + } + raw_spin_unlock_irqrestore(&blkg_stat_lock, flags); + out: +diff --git a/block/blk-settings.c b/block/blk-settings.c +index 9d6033e01f2e1..15319b217bf3f 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -751,6 +751,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, + unsigned int top, bottom, alignment, ret = 0; + + t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors); ++ t->max_user_sectors = min_not_zero(t->max_user_sectors, ++ b->max_user_sectors); + t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors); + t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors); + t->max_write_zeroes_sectors = min(t->max_write_zeroes_sectors, +diff --git a/drivers/base/base.h b/drivers/base/base.h +index 0738ccad08b2e..db4f910e8e36e 100644 +--- a/drivers/base/base.h ++++ b/drivers/base/base.h +@@ -192,11 +192,14 @@ extern struct kset *devices_kset; + void devices_kset_move_last(struct device *dev); + + #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS) +-void module_add_driver(struct module *mod, struct device_driver *drv); ++int module_add_driver(struct module *mod, struct device_driver *drv); + void module_remove_driver(struct device_driver *drv); + #else +-static inline void module_add_driver(struct module *mod, +- struct device_driver *drv) { } ++static inline int module_add_driver(struct module *mod, ++ struct device_driver *drv) ++{ ++ return 0; ++} + static inline void module_remove_driver(struct device_driver *drv) { } + #endif + +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index daee55c9b2d9e..ffea0728b8b2f 100644 +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -674,7 +674,12 @@ int bus_add_driver(struct device_driver *drv) + if (error) + goto out_del_list; + } +- module_add_driver(drv->owner, drv); ++ error = module_add_driver(drv->owner, drv); ++ if (error) { ++ printk(KERN_ERR "%s: failed to create module links for %s\n", ++ __func__, drv->name); ++ goto out_detach; ++ } + + error = driver_create_file(drv, &driver_attr_uevent); + if (error) { +@@ -699,6 +704,8 @@ int bus_add_driver(struct device_driver *drv) + + return 0; + ++out_detach: ++ driver_detach(drv); + out_del_list: + klist_del(&priv->knode_bus); + out_unregister: +diff --git a/drivers/base/module.c b/drivers/base/module.c +index 46ad4d636731d..a1b55da07127d 100644 +--- a/drivers/base/module.c ++++ b/drivers/base/module.c +@@ -30,14 +30,14 @@ static void module_create_drivers_dir(struct module_kobject *mk) + mutex_unlock(&drivers_dir_mutex); + } + +-void module_add_driver(struct module *mod, struct device_driver *drv) ++int module_add_driver(struct module *mod, struct device_driver *drv) + { + char *driver_name; +- int no_warn; + struct module_kobject *mk = NULL; ++ int ret; + + if (!drv) +- return; ++ return 0; + + if (mod) + mk = &mod->mkobj; +@@ -56,17 +56,37 @@ void module_add_driver(struct module *mod, struct device_driver *drv) + } + + if (!mk) +- return; ++ return 0; ++ ++ ret = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module"); ++ if (ret) ++ return ret; + +- /* Don't check return codes; these calls are idempotent */ +- no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module"); + driver_name = make_driver_name(drv); +- if (driver_name) { +- module_create_drivers_dir(mk); +- no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, +- driver_name); +- kfree(driver_name); ++ if (!driver_name) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ module_create_drivers_dir(mk); ++ if (!mk->drivers_dir) { ++ ret = -EINVAL; ++ goto out; + } ++ ++ ret = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, driver_name); ++ if (ret) ++ goto out; ++ ++ kfree(driver_name); ++ ++ return 0; ++out: ++ sysfs_remove_link(&drv->p->kobj, "module"); ++ sysfs_remove_link(mk->drivers_dir, driver_name); ++ kfree(driver_name); ++ ++ return ret; + } + + void module_remove_driver(struct device_driver *drv) +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index eed63f95e89d0..620679a0ac381 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -404,13 +404,25 @@ static int nullb_update_nr_hw_queues(struct nullb_device *dev, + static int nullb_apply_submit_queues(struct nullb_device *dev, + unsigned int submit_queues) + { +- return nullb_update_nr_hw_queues(dev, submit_queues, dev->poll_queues); ++ int ret; ++ ++ mutex_lock(&lock); ++ ret = nullb_update_nr_hw_queues(dev, submit_queues, dev->poll_queues); ++ mutex_unlock(&lock); ++ ++ return ret; + } + + static int nullb_apply_poll_queues(struct nullb_device *dev, + unsigned int poll_queues) + { +- return nullb_update_nr_hw_queues(dev, dev->submit_queues, poll_queues); ++ int ret; ++ ++ mutex_lock(&lock); ++ ret = nullb_update_nr_hw_queues(dev, dev->submit_queues, poll_queues); ++ mutex_unlock(&lock); ++ ++ return ret; + } + + NULLB_DEVICE_ATTR(size, ulong, NULL); +@@ -457,28 +469,32 @@ static ssize_t nullb_device_power_store(struct config_item *item, + if (ret < 0) + return ret; + ++ ret = count; ++ mutex_lock(&lock); + if (!dev->power && newp) { + if (test_and_set_bit(NULLB_DEV_FL_UP, &dev->flags)) +- return count; ++ goto out; ++ + ret = null_add_dev(dev); + if (ret) { + clear_bit(NULLB_DEV_FL_UP, &dev->flags); +- return ret; ++ goto out; + } + + set_bit(NULLB_DEV_FL_CONFIGURED, &dev->flags); + dev->power = newp; ++ ret = count; + } else if (dev->power && !newp) { + if (test_and_clear_bit(NULLB_DEV_FL_UP, &dev->flags)) { +- mutex_lock(&lock); + dev->power = newp; + null_del_dev(dev->nullb); +- mutex_unlock(&lock); + } + clear_bit(NULLB_DEV_FL_CONFIGURED, &dev->flags); + } + +- return count; ++out: ++ mutex_unlock(&lock); ++ return ret; + } + + CONFIGFS_ATTR(nullb_device_, power); +@@ -1918,15 +1934,12 @@ static int null_add_dev(struct nullb_device *dev) + nullb->q->queuedata = nullb; + blk_queue_flag_set(QUEUE_FLAG_NONROT, nullb->q); + +- mutex_lock(&lock); + rv = ida_alloc(&nullb_indexes, GFP_KERNEL); +- if (rv < 0) { +- mutex_unlock(&lock); ++ if (rv < 0) + goto out_cleanup_disk; +- } ++ + nullb->index = rv; + dev->index = rv; +- mutex_unlock(&lock); + + if (config_item_name(&dev->group.cg_item)) { + /* Use configfs dir name as the device name */ +@@ -1955,9 +1968,7 @@ static int null_add_dev(struct nullb_device *dev) + if (rv) + goto out_ida_free; + +- mutex_lock(&lock); + list_add_tail(&nullb->list, &nullb_list); +- mutex_unlock(&lock); + + pr_info("disk %s created\n", nullb->disk_name); + +@@ -2006,7 +2017,9 @@ static int null_create_dev(void) + if (!dev) + return -ENOMEM; + ++ mutex_lock(&lock); + ret = null_add_dev(dev); ++ mutex_unlock(&lock); + if (ret) { + null_free_dev(dev); + return ret; +@@ -2121,4 +2134,5 @@ module_init(null_init); + module_exit(null_exit); + + MODULE_AUTHOR("Jens Axboe <axboe@kernel.dk>"); ++MODULE_DESCRIPTION("multi queue aware block test driver"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c +index ee951b265213f..58e9dcc2a3087 100644 +--- a/drivers/char/ppdev.c ++++ b/drivers/char/ppdev.c +@@ -296,28 +296,35 @@ static int register_device(int minor, struct pp_struct *pp) + if (!port) { + pr_warn("%s: no associated port!\n", name); + rc = -ENXIO; +- goto err; ++ goto err_free_name; + } + + index = ida_alloc(&ida_index, GFP_KERNEL); ++ if (index < 0) { ++ pr_warn("%s: failed to get index!\n", name); ++ rc = index; ++ goto err_put_port; ++ } ++ + memset(&ppdev_cb, 0, sizeof(ppdev_cb)); + ppdev_cb.irq_func = pp_irq; + ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; + ppdev_cb.private = pp; + pdev = parport_register_dev_model(port, name, &ppdev_cb, index); +- parport_put_port(port); + + if (!pdev) { + pr_warn("%s: failed to register device!\n", name); + rc = -ENXIO; + ida_free(&ida_index, index); +- goto err; ++ goto err_put_port; + } + + pp->pdev = pdev; + pp->index = index; + dev_dbg(&pdev->dev, "registered pardevice\n"); +-err: ++err_put_port: ++ parport_put_port(port); ++err_free_name: + kfree(name); + return rc; + } +diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c +index 3f9eaf27b41b8..c9eca24bbad47 100644 +--- a/drivers/char/tpm/tpm_tis_spi_main.c ++++ b/drivers/char/tpm/tpm_tis_spi_main.c +@@ -37,6 +37,7 @@ + #include "tpm_tis_spi.h" + + #define MAX_SPI_FRAMESIZE 64 ++#define SPI_HDRSIZE 4 + + /* + * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short, +@@ -247,7 +248,7 @@ static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, + int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy, + int irq, const struct tpm_tis_phy_ops *phy_ops) + { +- phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); ++ phy->iobuf = devm_kmalloc(&spi->dev, SPI_HDRSIZE + MAX_SPI_FRAMESIZE, GFP_KERNEL); + if (!phy->iobuf) + return -ENOMEM; + +diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c +index 5c186e0a39b96..812b2948b6c65 100644 +--- a/drivers/cxl/core/region.c ++++ b/drivers/cxl/core/region.c +@@ -2719,6 +2719,7 @@ static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr) + if (i == 0) { + cxl_nvb = cxl_find_nvdimm_bridge(cxlmd); + if (!cxl_nvb) { ++ kfree(cxlr_pmem); + cxlr_pmem = ERR_PTR(-ENODEV); + goto out; + } +diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h +index e5f13260fc524..7c5cd069f10cc 100644 +--- a/drivers/cxl/core/trace.h ++++ b/drivers/cxl/core/trace.h +@@ -253,8 +253,8 @@ TRACE_EVENT(cxl_generic_event, + * DRAM Event Record + * CXL rev 3.0 section 8.2.9.2.1.2; Table 8-44 + */ +-#define CXL_DPA_FLAGS_MASK 0x3F +-#define CXL_DPA_MASK (~CXL_DPA_FLAGS_MASK) ++#define CXL_DPA_FLAGS_MASK GENMASK(1, 0) ++#define CXL_DPA_MASK GENMASK_ULL(63, 6) + + #define CXL_DPA_VOLATILE BIT(0) + #define CXL_DPA_NOT_REPAIRABLE BIT(1) +diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c +index 101394f16930f..237bce21d1e72 100644 +--- a/drivers/dma-buf/sync_debug.c ++++ b/drivers/dma-buf/sync_debug.c +@@ -110,12 +110,12 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) + + seq_printf(s, "%s: %d\n", obj->name, obj->value); + +- spin_lock_irq(&obj->lock); ++ spin_lock(&obj->lock); /* Caller already disabled IRQ. */ + list_for_each(pos, &obj->pt_list) { + struct sync_pt *pt = container_of(pos, struct sync_pt, link); + sync_print_fence(s, &pt->base, false); + } +- spin_unlock_irq(&obj->lock); ++ spin_unlock(&obj->lock); + } + + static void sync_print_sync_file(struct seq_file *s, +diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c +index 1398814d8fbb6..e3505e56784b1 100644 +--- a/drivers/dma/idma64.c ++++ b/drivers/dma/idma64.c +@@ -598,7 +598,9 @@ static int idma64_probe(struct idma64_chip *chip) + + idma64->dma.dev = chip->sysdev; + +- dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK); ++ ret = dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK); ++ if (ret) ++ return ret; + + ret = dma_async_device_register(&idma64->dma); + if (ret) +diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c +index 39935071174a3..fd9bbee4cc42f 100644 +--- a/drivers/dma/idxd/cdev.c ++++ b/drivers/dma/idxd/cdev.c +@@ -577,7 +577,6 @@ void idxd_wq_del_cdev(struct idxd_wq *wq) + struct idxd_cdev *idxd_cdev; + + idxd_cdev = wq->idxd_cdev; +- ida_destroy(&file_ida); + wq->idxd_cdev = NULL; + cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev)); + put_device(cdev_dev(idxd_cdev)); +diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig +index 5f869eacd19ab..3da94b3822923 100644 +--- a/drivers/extcon/Kconfig ++++ b/drivers/extcon/Kconfig +@@ -116,7 +116,8 @@ config EXTCON_MAX77843 + + config EXTCON_MAX8997 + tristate "Maxim MAX8997 EXTCON Support" +- depends on MFD_MAX8997 && IRQ_DOMAIN ++ depends on MFD_MAX8997 ++ select IRQ_DOMAIN + help + If you say yes here you get support for the MUIC device of + Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory +diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c +index 5f3a3e913d28f..d19c78a78ae3a 100644 +--- a/drivers/firmware/dmi-id.c ++++ b/drivers/firmware/dmi-id.c +@@ -169,9 +169,14 @@ static int dmi_dev_uevent(const struct device *dev, struct kobj_uevent_env *env) + return 0; + } + ++static void dmi_dev_release(struct device *dev) ++{ ++ kfree(dev); ++} ++ + static struct class dmi_class = { + .name = "dmi", +- .dev_release = (void(*)(struct device *)) kfree, ++ .dev_release = dmi_dev_release, + .dev_uevent = dmi_dev_uevent, + }; + +diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c +index 70e9789ff9de0..6a337f1f8787b 100644 +--- a/drivers/firmware/efi/libstub/fdt.c ++++ b/drivers/firmware/efi/libstub/fdt.c +@@ -335,8 +335,8 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, + + fail: + efi_free(fdt_size, fdt_addr); +- +- efi_bs_call(free_pool, priv.runtime_map); ++ if (!efi_novamap) ++ efi_bs_call(free_pool, priv.runtime_map); + + return EFI_LOAD_ERROR; + } +diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c +index d5a8182cf2e1c..1983fd3bf392e 100644 +--- a/drivers/firmware/efi/libstub/x86-stub.c ++++ b/drivers/firmware/efi/libstub/x86-stub.c +@@ -776,6 +776,26 @@ static void error(char *str) + efi_warn("Decompression failed: %s\n", str); + } + ++static const char *cmdline_memmap_override; ++ ++static efi_status_t parse_options(const char *cmdline) ++{ ++ static const char opts[][14] = { ++ "mem=", "memmap=", "efi_fake_mem=", "hugepages=" ++ }; ++ ++ for (int i = 0; i < ARRAY_SIZE(opts); i++) { ++ const char *p = strstr(cmdline, opts[i]); ++ ++ if (p == cmdline || (p > cmdline && isspace(p[-1]))) { ++ cmdline_memmap_override = opts[i]; ++ break; ++ } ++ } ++ ++ return efi_parse_options(cmdline); ++} ++ + static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) + { + unsigned long virt_addr = LOAD_PHYSICAL_ADDR; +@@ -807,6 +827,10 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) + !memcmp(efistub_fw_vendor(), ami, sizeof(ami))) { + efi_debug("AMI firmware v2.0 or older detected - disabling physical KASLR\n"); + seed[0] = 0; ++ } else if (cmdline_memmap_override) { ++ efi_info("%s detected on the kernel command line - disabling physical KASLR\n", ++ cmdline_memmap_override); ++ seed[0] = 0; + } + + boot_params_ptr->hdr.loadflags |= KASLR_FLAG; +@@ -883,7 +907,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle, + } + + #ifdef CONFIG_CMDLINE_BOOL +- status = efi_parse_options(CONFIG_CMDLINE); ++ status = parse_options(CONFIG_CMDLINE); + if (status != EFI_SUCCESS) { + efi_err("Failed to parse options\n"); + goto fail; +@@ -892,7 +916,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle, + if (!IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) { + unsigned long cmdline_paddr = ((u64)hdr->cmd_line_ptr | + ((u64)boot_params->ext_cmd_line_ptr << 32)); +- status = efi_parse_options((char *)cmdline_paddr); ++ status = parse_options((char *)cmdline_paddr); + if (status != EFI_SUCCESS) { + efi_err("Failed to parse options\n"); + goto fail; +diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c +index 79c473b3c7c3d..8ef395b49bf8a 100644 +--- a/drivers/fpga/fpga-bridge.c ++++ b/drivers/fpga/fpga-bridge.c +@@ -55,33 +55,26 @@ int fpga_bridge_disable(struct fpga_bridge *bridge) + } + EXPORT_SYMBOL_GPL(fpga_bridge_disable); + +-static struct fpga_bridge *__fpga_bridge_get(struct device *dev, ++static struct fpga_bridge *__fpga_bridge_get(struct device *bridge_dev, + struct fpga_image_info *info) + { + struct fpga_bridge *bridge; +- int ret = -ENODEV; + +- bridge = to_fpga_bridge(dev); ++ bridge = to_fpga_bridge(bridge_dev); + + bridge->info = info; + +- if (!mutex_trylock(&bridge->mutex)) { +- ret = -EBUSY; +- goto err_dev; +- } ++ if (!mutex_trylock(&bridge->mutex)) ++ return ERR_PTR(-EBUSY); + +- if (!try_module_get(dev->parent->driver->owner)) +- goto err_ll_mod; ++ if (!try_module_get(bridge->br_ops_owner)) { ++ mutex_unlock(&bridge->mutex); ++ return ERR_PTR(-ENODEV); ++ } + + dev_dbg(&bridge->dev, "get\n"); + + return bridge; +- +-err_ll_mod: +- mutex_unlock(&bridge->mutex); +-err_dev: +- put_device(dev); +- return ERR_PTR(ret); + } + + /** +@@ -98,13 +91,18 @@ static struct fpga_bridge *__fpga_bridge_get(struct device *dev, + struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, + struct fpga_image_info *info) + { +- struct device *dev; ++ struct fpga_bridge *bridge; ++ struct device *bridge_dev; + +- dev = class_find_device_by_of_node(&fpga_bridge_class, np); +- if (!dev) ++ bridge_dev = class_find_device_by_of_node(&fpga_bridge_class, np); ++ if (!bridge_dev) + return ERR_PTR(-ENODEV); + +- return __fpga_bridge_get(dev, info); ++ bridge = __fpga_bridge_get(bridge_dev, info); ++ if (IS_ERR(bridge)) ++ put_device(bridge_dev); ++ ++ return bridge; + } + EXPORT_SYMBOL_GPL(of_fpga_bridge_get); + +@@ -125,6 +123,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data) + struct fpga_bridge *fpga_bridge_get(struct device *dev, + struct fpga_image_info *info) + { ++ struct fpga_bridge *bridge; + struct device *bridge_dev; + + bridge_dev = class_find_device(&fpga_bridge_class, NULL, dev, +@@ -132,7 +131,11 @@ struct fpga_bridge *fpga_bridge_get(struct device *dev, + if (!bridge_dev) + return ERR_PTR(-ENODEV); + +- return __fpga_bridge_get(bridge_dev, info); ++ bridge = __fpga_bridge_get(bridge_dev, info); ++ if (IS_ERR(bridge)) ++ put_device(bridge_dev); ++ ++ return bridge; + } + EXPORT_SYMBOL_GPL(fpga_bridge_get); + +@@ -146,7 +149,7 @@ void fpga_bridge_put(struct fpga_bridge *bridge) + dev_dbg(&bridge->dev, "put\n"); + + bridge->info = NULL; +- module_put(bridge->dev.parent->driver->owner); ++ module_put(bridge->br_ops_owner); + mutex_unlock(&bridge->mutex); + put_device(&bridge->dev); + } +@@ -316,18 +319,19 @@ static struct attribute *fpga_bridge_attrs[] = { + ATTRIBUTE_GROUPS(fpga_bridge); + + /** +- * fpga_bridge_register - create and register an FPGA Bridge device ++ * __fpga_bridge_register - create and register an FPGA Bridge device + * @parent: FPGA bridge device from pdev + * @name: FPGA bridge name + * @br_ops: pointer to structure of fpga bridge ops + * @priv: FPGA bridge private data ++ * @owner: owner module containing the br_ops + * + * Return: struct fpga_bridge pointer or ERR_PTR() + */ + struct fpga_bridge * +-fpga_bridge_register(struct device *parent, const char *name, +- const struct fpga_bridge_ops *br_ops, +- void *priv) ++__fpga_bridge_register(struct device *parent, const char *name, ++ const struct fpga_bridge_ops *br_ops, ++ void *priv, struct module *owner) + { + struct fpga_bridge *bridge; + int id, ret; +@@ -357,6 +361,7 @@ fpga_bridge_register(struct device *parent, const char *name, + + bridge->name = name; + bridge->br_ops = br_ops; ++ bridge->br_ops_owner = owner; + bridge->priv = priv; + + bridge->dev.groups = br_ops->groups; +@@ -386,7 +391,7 @@ fpga_bridge_register(struct device *parent, const char *name, + + return ERR_PTR(ret); + } +-EXPORT_SYMBOL_GPL(fpga_bridge_register); ++EXPORT_SYMBOL_GPL(__fpga_bridge_register); + + /** + * fpga_bridge_unregister - unregister an FPGA bridge +diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c +index 06651389c5926..0f4035b089a2e 100644 +--- a/drivers/fpga/fpga-mgr.c ++++ b/drivers/fpga/fpga-mgr.c +@@ -664,20 +664,16 @@ static struct attribute *fpga_mgr_attrs[] = { + }; + ATTRIBUTE_GROUPS(fpga_mgr); + +-static struct fpga_manager *__fpga_mgr_get(struct device *dev) ++static struct fpga_manager *__fpga_mgr_get(struct device *mgr_dev) + { + struct fpga_manager *mgr; + +- mgr = to_fpga_manager(dev); ++ mgr = to_fpga_manager(mgr_dev); + +- if (!try_module_get(dev->parent->driver->owner)) +- goto err_dev; ++ if (!try_module_get(mgr->mops_owner)) ++ mgr = ERR_PTR(-ENODEV); + + return mgr; +- +-err_dev: +- put_device(dev); +- return ERR_PTR(-ENODEV); + } + + static int fpga_mgr_dev_match(struct device *dev, const void *data) +@@ -693,12 +689,18 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) + */ + struct fpga_manager *fpga_mgr_get(struct device *dev) + { +- struct device *mgr_dev = class_find_device(&fpga_mgr_class, NULL, dev, +- fpga_mgr_dev_match); ++ struct fpga_manager *mgr; ++ struct device *mgr_dev; ++ ++ mgr_dev = class_find_device(&fpga_mgr_class, NULL, dev, fpga_mgr_dev_match); + if (!mgr_dev) + return ERR_PTR(-ENODEV); + +- return __fpga_mgr_get(mgr_dev); ++ mgr = __fpga_mgr_get(mgr_dev); ++ if (IS_ERR(mgr)) ++ put_device(mgr_dev); ++ ++ return mgr; + } + EXPORT_SYMBOL_GPL(fpga_mgr_get); + +@@ -711,13 +713,18 @@ EXPORT_SYMBOL_GPL(fpga_mgr_get); + */ + struct fpga_manager *of_fpga_mgr_get(struct device_node *node) + { +- struct device *dev; ++ struct fpga_manager *mgr; ++ struct device *mgr_dev; + +- dev = class_find_device_by_of_node(&fpga_mgr_class, node); +- if (!dev) ++ mgr_dev = class_find_device_by_of_node(&fpga_mgr_class, node); ++ if (!mgr_dev) + return ERR_PTR(-ENODEV); + +- return __fpga_mgr_get(dev); ++ mgr = __fpga_mgr_get(mgr_dev); ++ if (IS_ERR(mgr)) ++ put_device(mgr_dev); ++ ++ return mgr; + } + EXPORT_SYMBOL_GPL(of_fpga_mgr_get); + +@@ -727,7 +734,7 @@ EXPORT_SYMBOL_GPL(of_fpga_mgr_get); + */ + void fpga_mgr_put(struct fpga_manager *mgr) + { +- module_put(mgr->dev.parent->driver->owner); ++ module_put(mgr->mops_owner); + put_device(&mgr->dev); + } + EXPORT_SYMBOL_GPL(fpga_mgr_put); +@@ -766,9 +773,10 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) + EXPORT_SYMBOL_GPL(fpga_mgr_unlock); + + /** +- * fpga_mgr_register_full - create and register an FPGA Manager device ++ * __fpga_mgr_register_full - create and register an FPGA Manager device + * @parent: fpga manager device from pdev + * @info: parameters for fpga manager ++ * @owner: owner module containing the ops + * + * The caller of this function is responsible for calling fpga_mgr_unregister(). + * Using devm_fpga_mgr_register_full() instead is recommended. +@@ -776,7 +784,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unlock); + * Return: pointer to struct fpga_manager pointer or ERR_PTR() + */ + struct fpga_manager * +-fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info) ++__fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, ++ struct module *owner) + { + const struct fpga_manager_ops *mops = info->mops; + struct fpga_manager *mgr; +@@ -804,6 +813,8 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in + + mutex_init(&mgr->ref_mutex); + ++ mgr->mops_owner = owner; ++ + mgr->name = info->name; + mgr->mops = info->mops; + mgr->priv = info->priv; +@@ -841,14 +852,15 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in + + return ERR_PTR(ret); + } +-EXPORT_SYMBOL_GPL(fpga_mgr_register_full); ++EXPORT_SYMBOL_GPL(__fpga_mgr_register_full); + + /** +- * fpga_mgr_register - create and register an FPGA Manager device ++ * __fpga_mgr_register - create and register an FPGA Manager device + * @parent: fpga manager device from pdev + * @name: fpga manager name + * @mops: pointer to structure of fpga manager ops + * @priv: fpga manager private data ++ * @owner: owner module containing the ops + * + * The caller of this function is responsible for calling fpga_mgr_unregister(). + * Using devm_fpga_mgr_register() instead is recommended. This simple +@@ -859,8 +871,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_register_full); + * Return: pointer to struct fpga_manager pointer or ERR_PTR() + */ + struct fpga_manager * +-fpga_mgr_register(struct device *parent, const char *name, +- const struct fpga_manager_ops *mops, void *priv) ++__fpga_mgr_register(struct device *parent, const char *name, ++ const struct fpga_manager_ops *mops, void *priv, struct module *owner) + { + struct fpga_manager_info info = { 0 }; + +@@ -868,9 +880,9 @@ fpga_mgr_register(struct device *parent, const char *name, + info.mops = mops; + info.priv = priv; + +- return fpga_mgr_register_full(parent, &info); ++ return __fpga_mgr_register_full(parent, &info, owner); + } +-EXPORT_SYMBOL_GPL(fpga_mgr_register); ++EXPORT_SYMBOL_GPL(__fpga_mgr_register); + + /** + * fpga_mgr_unregister - unregister an FPGA manager +@@ -900,9 +912,10 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res) + } + + /** +- * devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register() ++ * __devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register() + * @parent: fpga manager device from pdev + * @info: parameters for fpga manager ++ * @owner: owner module containing the ops + * + * Return: fpga manager pointer on success, negative error code otherwise. + * +@@ -910,7 +923,8 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res) + * function will be called automatically when the managing device is detached. + */ + struct fpga_manager * +-devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info) ++__devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, ++ struct module *owner) + { + struct fpga_mgr_devres *dr; + struct fpga_manager *mgr; +@@ -919,7 +933,7 @@ devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_inf + if (!dr) + return ERR_PTR(-ENOMEM); + +- mgr = fpga_mgr_register_full(parent, info); ++ mgr = __fpga_mgr_register_full(parent, info, owner); + if (IS_ERR(mgr)) { + devres_free(dr); + return mgr; +@@ -930,14 +944,15 @@ devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_inf + + return mgr; + } +-EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full); ++EXPORT_SYMBOL_GPL(__devm_fpga_mgr_register_full); + + /** +- * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register() ++ * __devm_fpga_mgr_register - resource managed variant of fpga_mgr_register() + * @parent: fpga manager device from pdev + * @name: fpga manager name + * @mops: pointer to structure of fpga manager ops + * @priv: fpga manager private data ++ * @owner: owner module containing the ops + * + * Return: fpga manager pointer on success, negative error code otherwise. + * +@@ -946,8 +961,9 @@ EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full); + * device is detached. + */ + struct fpga_manager * +-devm_fpga_mgr_register(struct device *parent, const char *name, +- const struct fpga_manager_ops *mops, void *priv) ++__devm_fpga_mgr_register(struct device *parent, const char *name, ++ const struct fpga_manager_ops *mops, void *priv, ++ struct module *owner) + { + struct fpga_manager_info info = { 0 }; + +@@ -955,9 +971,9 @@ devm_fpga_mgr_register(struct device *parent, const char *name, + info.mops = mops; + info.priv = priv; + +- return devm_fpga_mgr_register_full(parent, &info); ++ return __devm_fpga_mgr_register_full(parent, &info, owner); + } +-EXPORT_SYMBOL_GPL(devm_fpga_mgr_register); ++EXPORT_SYMBOL_GPL(__devm_fpga_mgr_register); + + static void fpga_mgr_dev_release(struct device *dev) + { +diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c +index b364a929425ce..753cd142503e0 100644 +--- a/drivers/fpga/fpga-region.c ++++ b/drivers/fpga/fpga-region.c +@@ -53,7 +53,7 @@ static struct fpga_region *fpga_region_get(struct fpga_region *region) + } + + get_device(dev); +- if (!try_module_get(dev->parent->driver->owner)) { ++ if (!try_module_get(region->ops_owner)) { + put_device(dev); + mutex_unlock(®ion->mutex); + return ERR_PTR(-ENODEV); +@@ -75,7 +75,7 @@ static void fpga_region_put(struct fpga_region *region) + + dev_dbg(dev, "put\n"); + +- module_put(dev->parent->driver->owner); ++ module_put(region->ops_owner); + put_device(dev); + mutex_unlock(®ion->mutex); + } +@@ -181,14 +181,16 @@ static struct attribute *fpga_region_attrs[] = { + ATTRIBUTE_GROUPS(fpga_region); + + /** +- * fpga_region_register_full - create and register an FPGA Region device ++ * __fpga_region_register_full - create and register an FPGA Region device + * @parent: device parent + * @info: parameters for FPGA Region ++ * @owner: module containing the get_bridges function + * + * Return: struct fpga_region or ERR_PTR() + */ + struct fpga_region * +-fpga_region_register_full(struct device *parent, const struct fpga_region_info *info) ++__fpga_region_register_full(struct device *parent, const struct fpga_region_info *info, ++ struct module *owner) + { + struct fpga_region *region; + int id, ret = 0; +@@ -213,6 +215,7 @@ fpga_region_register_full(struct device *parent, const struct fpga_region_info * + region->compat_id = info->compat_id; + region->priv = info->priv; + region->get_bridges = info->get_bridges; ++ region->ops_owner = owner; + + mutex_init(®ion->mutex); + INIT_LIST_HEAD(®ion->bridge_list); +@@ -241,13 +244,14 @@ fpga_region_register_full(struct device *parent, const struct fpga_region_info * + + return ERR_PTR(ret); + } +-EXPORT_SYMBOL_GPL(fpga_region_register_full); ++EXPORT_SYMBOL_GPL(__fpga_region_register_full); + + /** +- * fpga_region_register - create and register an FPGA Region device ++ * __fpga_region_register - create and register an FPGA Region device + * @parent: device parent + * @mgr: manager that programs this region + * @get_bridges: optional function to get bridges to a list ++ * @owner: module containing the get_bridges function + * + * This simple version of the register function should be sufficient for most users. + * The fpga_region_register_full() function is available for users that need to +@@ -256,17 +260,17 @@ EXPORT_SYMBOL_GPL(fpga_region_register_full); + * Return: struct fpga_region or ERR_PTR() + */ + struct fpga_region * +-fpga_region_register(struct device *parent, struct fpga_manager *mgr, +- int (*get_bridges)(struct fpga_region *)) ++__fpga_region_register(struct device *parent, struct fpga_manager *mgr, ++ int (*get_bridges)(struct fpga_region *), struct module *owner) + { + struct fpga_region_info info = { 0 }; + + info.mgr = mgr; + info.get_bridges = get_bridges; + +- return fpga_region_register_full(parent, &info); ++ return __fpga_region_register_full(parent, &info, owner); + } +-EXPORT_SYMBOL_GPL(fpga_region_register); ++EXPORT_SYMBOL_GPL(__fpga_region_register); + + /** + * fpga_region_unregister - unregister an FPGA region +diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c +index 7f140df40f35b..c1e190d3ea244 100644 +--- a/drivers/gpio/gpiolib-acpi.c ++++ b/drivers/gpio/gpiolib-acpi.c +@@ -128,7 +128,24 @@ static bool acpi_gpio_deferred_req_irqs_done; + + static int acpi_gpiochip_find(struct gpio_chip *gc, const void *data) + { +- return device_match_acpi_handle(&gc->gpiodev->dev, data); ++ /* First check the actual GPIO device */ ++ if (device_match_acpi_handle(&gc->gpiodev->dev, data)) ++ return true; ++ ++ /* ++ * When the ACPI device is artificially split to the banks of GPIOs, ++ * where each of them is represented by a separate GPIO device, ++ * the firmware node of the physical device may not be shared among ++ * the banks as they may require different values for the same property, ++ * e.g., number of GPIOs in a certain bank. In such case the ACPI handle ++ * of a GPIO device is NULL and can not be used. Hence we have to check ++ * the parent device to be sure that there is no match before bailing ++ * out. ++ */ ++ if (gc->parent) ++ return device_match_acpi_handle(gc->parent, data); ++ ++ return false; + } + + /** +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 7753a2e64d411..941d6e379b8a6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -5809,13 +5809,18 @@ static void amdgpu_device_partner_bandwidth(struct amdgpu_device *adev, + *speed = PCI_SPEED_UNKNOWN; + *width = PCIE_LNK_WIDTH_UNKNOWN; + +- while ((parent = pci_upstream_bridge(parent))) { +- /* skip upstream/downstream switches internal to dGPU*/ +- if (parent->vendor == PCI_VENDOR_ID_ATI) +- continue; +- *speed = pcie_get_speed_cap(parent); +- *width = pcie_get_width_cap(parent); +- break; ++ if (amdgpu_device_pcie_dynamic_switching_supported(adev)) { ++ while ((parent = pci_upstream_bridge(parent))) { ++ /* skip upstream/downstream switches internal to dGPU*/ ++ if (parent->vendor == PCI_VENDOR_ID_ATI) ++ continue; ++ *speed = pcie_get_speed_cap(parent); ++ *width = pcie_get_width_cap(parent); ++ break; ++ } ++ } else { ++ /* use the current speeds rather than max if switching is not supported */ ++ pcie_bandwidth_available(adev->pdev, NULL, speed, width); + } + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +index b53c8fd4e8cf3..d89d6829f1df4 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +@@ -431,16 +431,16 @@ static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev, + + static int gfx_v9_4_3_init_microcode(struct amdgpu_device *adev) + { +- const char *chip_name; ++ char ucode_prefix[15]; + int r; + +- chip_name = "gc_9_4_3"; ++ amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); + +- r = gfx_v9_4_3_init_rlc_microcode(adev, chip_name); ++ r = gfx_v9_4_3_init_rlc_microcode(adev, ucode_prefix); + if (r) + return r; + +- r = gfx_v9_4_3_init_cp_compute_microcode(adev, chip_name); ++ r = gfx_v9_4_3_init_cp_compute_microcode(adev, ucode_prefix); + if (r) + return r; + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index cb31a699c6622..1a269099f19f8 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -613,6 +613,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + &connector->base, + dev->mode_config.tile_property, + 0); ++ connector->colorspace_property = master->base.colorspace_property; ++ if (connector->colorspace_property) ++ drm_connector_attach_colorspace_property(connector); + + drm_connector_set_path_property(connector, pathprop); + +diff --git a/drivers/gpu/drm/bridge/imx/Kconfig b/drivers/gpu/drm/bridge/imx/Kconfig +index 5965e8027529a..8dd89efa8ea7d 100644 +--- a/drivers/gpu/drm/bridge/imx/Kconfig ++++ b/drivers/gpu/drm/bridge/imx/Kconfig +@@ -8,8 +8,8 @@ config DRM_IMX8MP_DW_HDMI_BRIDGE + depends on OF + depends on COMMON_CLK + select DRM_DW_HDMI +- select DRM_IMX8MP_HDMI_PVI +- select PHY_FSL_SAMSUNG_HDMI_PHY ++ imply DRM_IMX8MP_HDMI_PVI ++ imply PHY_FSL_SAMSUNG_HDMI_PHY + help + Choose this to enable support for the internal HDMI encoder found + on the i.MX8MP SoC. +diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c +index fea4f00a20f83..c737670631929 100644 +--- a/drivers/gpu/drm/bridge/tc358775.c ++++ b/drivers/gpu/drm/bridge/tc358775.c +@@ -454,10 +454,6 @@ static void tc_bridge_enable(struct drm_bridge *bridge) + dev_dbg(tc->dev, "bus_formats %04x bpc %d\n", + connector->display_info.bus_formats[0], + tc->bpc); +- /* +- * Default hardware register settings of tc358775 configured +- * with MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA jeida-24 format +- */ + if (connector->display_info.bus_formats[0] == + MEDIA_BUS_FMT_RGB888_1X7X4_SPWG) { + /* VESA-24 */ +@@ -468,14 +464,15 @@ static void tc_bridge_enable(struct drm_bridge *bridge) + d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2)); + d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); + d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6)); +- } else { /* MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - JEIDA-18 */ +- d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3)); +- d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_L0, LVI_R5, LVI_G0)); +- d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_L0, LVI_L0)); +- d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0)); +- d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_L0, LVI_L0, LVI_B1, LVI_B2)); +- d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); +- d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_L0)); ++ } else { ++ /* JEIDA-18 and JEIDA-24 */ ++ d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R2, LVI_R3, LVI_R4, LVI_R5)); ++ d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R6, LVI_R1, LVI_R7, LVI_G2)); ++ d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G3, LVI_G4, LVI_G0, LVI_G1)); ++ d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G5, LVI_G6, LVI_G7, LVI_B2)); ++ d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B0, LVI_B1, LVI_B3, LVI_B4)); ++ d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B5, LVI_B6, LVI_B7, LVI_L0)); ++ d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R0)); + } + + d2l_write(tc->i2c, VFUEN, VFUEN_EN); +diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c +index 4814b7b6d1fd1..57a7ed13f9965 100644 +--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c ++++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c +@@ -478,7 +478,6 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, + dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret); + /* On failure, disable PLL again and exit. */ + regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00); +- regulator_disable(ctx->vcc); + return; + } + +diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c +index 7a6dc371c384e..bc6209df0f680 100644 +--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c ++++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c +@@ -919,6 +919,12 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt) + if (IS_DG2(gt->i915)) { + u8 first_ccs = __ffs(CCS_MASK(gt)); + ++ /* ++ * Store the number of active cslices before ++ * changing the CCS engine configuration ++ */ ++ gt->ccs.cslices = CCS_MASK(gt); ++ + /* Mask off all the CCS engine */ + info->engine_mask &= ~GENMASK(CCS3, CCS0); + /* Put back in the first CCS engine */ +diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c +index 99b71bb7da0a6..3c62a44e9106c 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c ++++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c +@@ -19,7 +19,7 @@ unsigned int intel_gt_apply_ccs_mode(struct intel_gt *gt) + + /* Build the value for the fixed CCS load balancing */ + for (cslice = 0; cslice < I915_MAX_CCS; cslice++) { +- if (CCS_MASK(gt) & BIT(cslice)) ++ if (gt->ccs.cslices & BIT(cslice)) + /* + * If available, assign the cslice + * to the first available engine... +diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h +index def7dd0eb6f19..cfdd2ad5e9549 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h ++++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h +@@ -207,6 +207,14 @@ struct intel_gt { + [MAX_ENGINE_INSTANCE + 1]; + enum intel_submission_method submission_method; + ++ struct { ++ /* ++ * Mask of the non fused CCS slices ++ * to be used for the load balancing ++ */ ++ intel_engine_mask_t cslices; ++ } ccs; ++ + /* + * Default address space (either GGTT or ppGTT depending on arch). + * +diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +index 58012edd4eb0e..4f4f53c42a9c5 100644 +--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h ++++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +@@ -29,9 +29,9 @@ + */ + + #define GUC_KLV_LEN_MIN 1u +-#define GUC_KLV_0_KEY (0xffff << 16) +-#define GUC_KLV_0_LEN (0xffff << 0) +-#define GUC_KLV_n_VALUE (0xffffffff << 0) ++#define GUC_KLV_0_KEY (0xffffu << 16) ++#define GUC_KLV_0_LEN (0xffffu << 0) ++#define GUC_KLV_n_VALUE (0xffffffffu << 0) + + /** + * DOC: GuC Self Config KLVs +diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c +index 0ba72102636aa..536366956447a 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dp.c ++++ b/drivers/gpu/drm/mediatek/mtk_dp.c +@@ -2104,7 +2104,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, + + if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP && + !mtk_dp->train_info.cable_plugged_in) { +- ret = -EAGAIN; ++ ret = -EIO; + goto err; + } + +diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c +index a6bc1bdb3d0d8..a10cff3ca1fef 100644 +--- a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c ++++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c +@@ -95,6 +95,7 @@ static int dw_mipi_dsi_phy_init(void *priv_data) + return ret; + } + ++ clk_disable_unprepare(mipi_dsi->px_clk); + ret = clk_set_rate(mipi_dsi->px_clk, mipi_dsi->mode->clock * 1000); + + if (ret) { +@@ -103,6 +104,12 @@ static int dw_mipi_dsi_phy_init(void *priv_data) + return ret; + } + ++ ret = clk_prepare_enable(mipi_dsi->px_clk); ++ if (ret) { ++ dev_err(mipi_dsi->dev, "Failed to enable DSI Pixel clock (ret %d)\n", ret); ++ return ret; ++ } ++ + switch (mipi_dsi->dsi_device->format) { + case MIPI_DSI_FMT_RGB888: + dpi_data_format = DPI_COLOR_24BIT; +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +index cf0b1de1c0712..7b72327df7f3f 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +@@ -284,7 +284,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) + + a6xx_set_pagetable(a6xx_gpu, ring, submit->queue->ctx); + +- get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0), ++ get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0), + rbmemptr_stats(ring, index, cpcycles_start)); + get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER, + rbmemptr_stats(ring, index, alwayson_start)); +@@ -330,7 +330,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) + OUT_PKT7(ring, CP_SET_MARKER, 1); + OUT_RING(ring, 0x00e); /* IB1LIST end */ + +- get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0), ++ get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0), + rbmemptr_stats(ring, index, cpcycles_end)); + get_stats_counter(ring, REG_A6XX_CP_ALWAYS_ON_COUNTER, + rbmemptr_stats(ring, index, alwayson_end)); +@@ -3062,7 +3062,8 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) + + ret = a6xx_set_supported_hw(&pdev->dev, config->info); + if (ret) { +- a6xx_destroy(&(a6xx_gpu->base.base)); ++ a6xx_llc_slices_destroy(a6xx_gpu); ++ kfree(a6xx_gpu); + return ERR_PTR(ret); + } + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +index fc1d5736d7fcc..489be1c0c7046 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +@@ -448,9 +448,6 @@ static void dpu_encoder_phys_cmd_enable_helper( + + _dpu_encoder_phys_cmd_pingpong_config(phys_enc); + +- if (!dpu_encoder_phys_cmd_is_master(phys_enc)) +- return; +- + ctl = phys_enc->hw_ctl; + ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx); + } +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +index a06f69d0b257d..2e50049f2f850 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +@@ -545,6 +545,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, + { + struct dpu_hw_blk_reg_map *c = &ctx->hw; + u32 intf_active = 0; ++ u32 dsc_active = 0; + u32 wb_active = 0; + u32 mode_sel = 0; + +@@ -560,6 +561,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, + + intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE); + wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE); ++ dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE); + + if (cfg->intf) + intf_active |= BIT(cfg->intf - INTF_0); +@@ -567,17 +569,18 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, + if (cfg->wb) + wb_active |= BIT(cfg->wb - WB_0); + ++ if (cfg->dsc) ++ dsc_active |= cfg->dsc; ++ + DPU_REG_WRITE(c, CTL_TOP, mode_sel); + DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); + DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); ++ DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active); + + if (cfg->merge_3d) + DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, + BIT(cfg->merge_3d - MERGE_3D_0)); + +- if (cfg->dsc) +- DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc); +- + if (cfg->cdm) + DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm); + } +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +index 6a0a74832fb64..b85881aab0478 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +@@ -223,9 +223,11 @@ static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, unsigned int + + VERB("IRQ=[%d, %d]\n", DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); + +- if (!irq_entry->cb) ++ if (!irq_entry->cb) { + DRM_ERROR("no registered cb, IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); ++ return; ++ } + + atomic_inc(&irq_entry->count); + +diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c +index 9d86a6aca6f2a..c80be74cf10b5 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_host.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_host.c +@@ -356,8 +356,8 @@ int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) + { + int ret; + +- DBG("Set clk rates: pclk=%d, byteclk=%lu", +- msm_host->mode->clock, msm_host->byte_clk_rate); ++ DBG("Set clk rates: pclk=%lu, byteclk=%lu", ++ msm_host->pixel_clk_rate, msm_host->byte_clk_rate); + + ret = dev_pm_opp_set_rate(&msm_host->pdev->dev, + msm_host->byte_clk_rate); +@@ -430,9 +430,9 @@ int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host) + { + int ret; + +- DBG("Set clk rates: pclk=%d, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", +- msm_host->mode->clock, msm_host->byte_clk_rate, +- msm_host->esc_clk_rate, msm_host->src_clk_rate); ++ DBG("Set clk rates: pclk=%lu, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", ++ msm_host->pixel_clk_rate, msm_host->byte_clk_rate, ++ msm_host->esc_clk_rate, msm_host->src_clk_rate); + + ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate); + if (ret) { +diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c +index 80f74ee0fc786..47e53e17b4e58 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c ++++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c +@@ -272,6 +272,9 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) + getparam->value = (u64)ttm_resource_manager_usage(vram_mgr); + break; + } ++ case NOUVEAU_GETPARAM_HAS_VMA_TILEMODE: ++ getparam->value = 1; ++ break; + default: + NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param); + return -EINVAL; +diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c +index db8cbf6151129..186add400ea5f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bo.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c +@@ -241,28 +241,28 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, + } + + nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG); +- if (!nouveau_cli_uvmm(cli) || internal) { +- /* for BO noVM allocs, don't assign kinds */ +- if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) { +- nvbo->kind = (tile_flags & 0x0000ff00) >> 8; +- if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { +- kfree(nvbo); +- return ERR_PTR(-EINVAL); +- } + +- nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; +- } else if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { +- nvbo->kind = (tile_flags & 0x00007f00) >> 8; +- nvbo->comp = (tile_flags & 0x00030000) >> 16; +- if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { +- kfree(nvbo); +- return ERR_PTR(-EINVAL); +- } +- } else { +- nvbo->zeta = (tile_flags & 0x00000007); ++ if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) { ++ nvbo->kind = (tile_flags & 0x0000ff00) >> 8; ++ if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { ++ kfree(nvbo); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; ++ } else if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { ++ nvbo->kind = (tile_flags & 0x00007f00) >> 8; ++ nvbo->comp = (tile_flags & 0x00030000) >> 16; ++ if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { ++ kfree(nvbo); ++ return ERR_PTR(-EINVAL); + } +- nvbo->mode = tile_mode; ++ } else { ++ nvbo->zeta = (tile_flags & 0x00000007); ++ } ++ nvbo->mode = tile_mode; + ++ if (!nouveau_cli_uvmm(cli) || internal) { + /* Determine the desirable target GPU page size for the buffer. */ + for (i = 0; i < vmm->page_nr; i++) { + /* Because we cannot currently allow VMM maps to fail +@@ -304,12 +304,6 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, + } + nvbo->page = vmm->page[pi].shift; + } else { +- /* reject other tile flags when in VM mode. */ +- if (tile_mode) +- return ERR_PTR(-EINVAL); +- if (tile_flags & ~NOUVEAU_GEM_TILE_NONCONTIG) +- return ERR_PTR(-EINVAL); +- + /* Determine the desirable target GPU page size for the buffer. */ + for (i = 0; i < vmm->page_nr; i++) { + /* Because we cannot currently allow VMM maps to fail +diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +index 88e80fe98112d..e8f385b9c6182 100644 +--- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c ++++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +@@ -282,15 +282,15 @@ static const struct drm_display_mode et028013dma_mode = { + static const struct drm_display_mode jt240mhqs_hwt_ek_e3_mode = { + .clock = 6000, + .hdisplay = 240, +- .hsync_start = 240 + 28, +- .hsync_end = 240 + 28 + 10, +- .htotal = 240 + 28 + 10 + 10, ++ .hsync_start = 240 + 38, ++ .hsync_end = 240 + 38 + 10, ++ .htotal = 240 + 38 + 10 + 10, + .vdisplay = 280, +- .vsync_start = 280 + 8, +- .vsync_end = 280 + 8 + 4, +- .vtotal = 280 + 8 + 4 + 4, +- .width_mm = 43, +- .height_mm = 37, ++ .vsync_start = 280 + 48, ++ .vsync_end = 280 + 48 + 4, ++ .vtotal = 280 + 48 + 4 + 4, ++ .width_mm = 37, ++ .height_mm = 43, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, + }; + +diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c +index d32ff3857e658..b3b37ed832ca0 100644 +--- a/drivers/gpu/drm/xe/xe_device.c ++++ b/drivers/gpu/drm/xe/xe_device.c +@@ -389,8 +389,14 @@ static int xe_set_dma_info(struct xe_device *xe) + return err; + } + +-/* +- * Initialize MMIO resources that don't require any knowledge about tile count. ++/** ++ * xe_device_probe_early: Device early probe ++ * @xe: xe device instance ++ * ++ * Initialize MMIO resources that don't require any ++ * knowledge about tile count. Also initialize pcode ++ * ++ * Return: 0 on success, error code on failure + */ + int xe_device_probe_early(struct xe_device *xe) + { +@@ -404,6 +410,10 @@ int xe_device_probe_early(struct xe_device *xe) + if (err) + return err; + ++ err = xe_pcode_probe_early(xe); ++ if (err) ++ return err; ++ + return 0; + } + +@@ -482,11 +492,8 @@ int xe_device_probe(struct xe_device *xe) + if (err) + return err; + +- for_each_gt(gt, xe, id) { +- err = xe_pcode_probe(gt); +- if (err) +- return err; +- } ++ for_each_gt(gt, xe, id) ++ xe_pcode_init(gt); + + err = xe_display_init_noirq(xe); + if (err) +diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c +index 2ba4fb9511f63..aca519f5b85d9 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.c ++++ b/drivers/gpu/drm/xe/xe_migrate.c +@@ -33,7 +33,6 @@ + #include "xe_sync.h" + #include "xe_trace.h" + #include "xe_vm.h" +-#include "xe_wa.h" + + /** + * struct xe_migrate - migrate context. +@@ -299,10 +298,6 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, + } + + /* +- * Due to workaround 16017236439, odd instance hardware copy engines are +- * faster than even instance ones. +- * This function returns the mask involving all fast copy engines and the +- * reserved copy engine to be used as logical mask for migrate engine. + * Including the reserved copy engine is required to avoid deadlocks due to + * migrate jobs servicing the faults gets stuck behind the job that faulted. + */ +@@ -316,8 +311,7 @@ static u32 xe_migrate_usm_logical_mask(struct xe_gt *gt) + if (hwe->class != XE_ENGINE_CLASS_COPY) + continue; + +- if (!XE_WA(gt, 16017236439) || +- xe_gt_is_usm_hwe(gt, hwe) || hwe->instance & 1) ++ if (xe_gt_is_usm_hwe(gt, hwe)) + logical_mask |= BIT(hwe->logical_instance); + } + +@@ -368,6 +362,10 @@ struct xe_migrate *xe_migrate_init(struct xe_tile *tile) + if (!hwe || !logical_mask) + return ERR_PTR(-EINVAL); + ++ /* ++ * XXX: Currently only reserving 1 (likely slow) BCS instance on ++ * PVC, may want to revisit if performance is needed. ++ */ + m->q = xe_exec_queue_create(xe, vm, logical_mask, 1, hwe, + EXEC_QUEUE_FLAG_KERNEL | + EXEC_QUEUE_FLAG_PERMANENT | +diff --git a/drivers/gpu/drm/xe/xe_pcode.c b/drivers/gpu/drm/xe/xe_pcode.c +index b324dc2a5debe..81f4ae2ea08f3 100644 +--- a/drivers/gpu/drm/xe/xe_pcode.c ++++ b/drivers/gpu/drm/xe/xe_pcode.c +@@ -10,6 +10,7 @@ + + #include <drm/drm_managed.h> + ++#include "xe_device.h" + #include "xe_gt.h" + #include "xe_mmio.h" + #include "xe_pcode_api.h" +@@ -43,8 +44,6 @@ static int pcode_mailbox_status(struct xe_gt *gt) + [PCODE_ERROR_MASK] = {-EPROTO, "Unknown"}, + }; + +- lockdep_assert_held(>->pcode.lock); +- + err = xe_mmio_read32(gt, PCODE_MAILBOX) & PCODE_ERROR_MASK; + if (err) { + drm_err(>_to_xe(gt)->drm, "PCODE Mailbox failed: %d %s", err, +@@ -55,17 +54,15 @@ static int pcode_mailbox_status(struct xe_gt *gt) + return 0; + } + +-static int pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1, +- unsigned int timeout_ms, bool return_data, +- bool atomic) ++static int __pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1, ++ unsigned int timeout_ms, bool return_data, ++ bool atomic) + { + int err; + + if (gt_to_xe(gt)->info.skip_pcode) + return 0; + +- lockdep_assert_held(>->pcode.lock); +- + if ((xe_mmio_read32(gt, PCODE_MAILBOX) & PCODE_READY) != 0) + return -EAGAIN; + +@@ -87,6 +84,18 @@ static int pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1, + return pcode_mailbox_status(gt); + } + ++static int pcode_mailbox_rw(struct xe_gt *gt, u32 mbox, u32 *data0, u32 *data1, ++ unsigned int timeout_ms, bool return_data, ++ bool atomic) ++{ ++ if (gt_to_xe(gt)->info.skip_pcode) ++ return 0; ++ ++ lockdep_assert_held(>->pcode.lock); ++ ++ return __pcode_mailbox_rw(gt, mbox, data0, data1, timeout_ms, return_data, atomic); ++} ++ + int xe_pcode_write_timeout(struct xe_gt *gt, u32 mbox, u32 data, int timeout) + { + int err; +@@ -109,15 +118,19 @@ int xe_pcode_read(struct xe_gt *gt, u32 mbox, u32 *val, u32 *val1) + return err; + } + +-static int xe_pcode_try_request(struct xe_gt *gt, u32 mbox, +- u32 request, u32 reply_mask, u32 reply, +- u32 *status, bool atomic, int timeout_us) ++static int pcode_try_request(struct xe_gt *gt, u32 mbox, ++ u32 request, u32 reply_mask, u32 reply, ++ u32 *status, bool atomic, int timeout_us, bool locked) + { + int slept, wait = 10; + + for (slept = 0; slept < timeout_us; slept += wait) { +- *status = pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true, +- atomic); ++ if (locked) ++ *status = pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true, ++ atomic); ++ else ++ *status = __pcode_mailbox_rw(gt, mbox, &request, NULL, 1, true, ++ atomic); + if ((*status == 0) && ((request & reply_mask) == reply)) + return 0; + +@@ -158,8 +171,8 @@ int xe_pcode_request(struct xe_gt *gt, u32 mbox, u32 request, + + mutex_lock(>->pcode.lock); + +- ret = xe_pcode_try_request(gt, mbox, request, reply_mask, reply, &status, +- false, timeout_base_ms * 1000); ++ ret = pcode_try_request(gt, mbox, request, reply_mask, reply, &status, ++ false, timeout_base_ms * 1000, true); + if (!ret) + goto out; + +@@ -177,8 +190,8 @@ int xe_pcode_request(struct xe_gt *gt, u32 mbox, u32 request, + "PCODE timeout, retrying with preemption disabled\n"); + drm_WARN_ON_ONCE(>_to_xe(gt)->drm, timeout_base_ms > 1); + preempt_disable(); +- ret = xe_pcode_try_request(gt, mbox, request, reply_mask, reply, &status, +- true, timeout_base_ms * 1000); ++ ret = pcode_try_request(gt, mbox, request, reply_mask, reply, &status, ++ true, 50 * 1000, true); + preempt_enable(); + + out: +@@ -238,59 +251,71 @@ int xe_pcode_init_min_freq_table(struct xe_gt *gt, u32 min_gt_freq, + } + + /** +- * xe_pcode_init - Ensure PCODE is initialized +- * @gt: gt instance ++ * xe_pcode_ready - Ensure PCODE is initialized ++ * @xe: xe instance ++ * @locked: true if lock held, false otherwise + * +- * This function ensures that PCODE is properly initialized. To be called during +- * probe and resume paths. ++ * PCODE init mailbox is polled only on root gt of root tile ++ * as the root tile provides the initialization is complete only ++ * after all the tiles have completed the initialization. ++ * Called only on early probe without locks and with locks in ++ * resume path. + * +- * It returns 0 on success, and -error number on failure. ++ * Returns 0 on success, and -error number on failure. + */ +-int xe_pcode_init(struct xe_gt *gt) ++int xe_pcode_ready(struct xe_device *xe, bool locked) + { + u32 status, request = DGFX_GET_INIT_STATUS; ++ struct xe_gt *gt = xe_root_mmio_gt(xe); + int timeout_us = 180000000; /* 3 min */ + int ret; + +- if (gt_to_xe(gt)->info.skip_pcode) ++ if (xe->info.skip_pcode) + return 0; + +- if (!IS_DGFX(gt_to_xe(gt))) ++ if (!IS_DGFX(xe)) + return 0; + +- mutex_lock(>->pcode.lock); +- ret = xe_pcode_try_request(gt, DGFX_PCODE_STATUS, request, +- DGFX_INIT_STATUS_COMPLETE, +- DGFX_INIT_STATUS_COMPLETE, +- &status, false, timeout_us); +- mutex_unlock(>->pcode.lock); ++ if (locked) ++ mutex_lock(>->pcode.lock); ++ ++ ret = pcode_try_request(gt, DGFX_PCODE_STATUS, request, ++ DGFX_INIT_STATUS_COMPLETE, ++ DGFX_INIT_STATUS_COMPLETE, ++ &status, false, timeout_us, locked); ++ ++ if (locked) ++ mutex_unlock(>->pcode.lock); + + if (ret) +- drm_err(>_to_xe(gt)->drm, ++ drm_err(&xe->drm, + "PCODE initialization timedout after: 3 min\n"); + + return ret; + } + + /** +- * xe_pcode_probe - Prepare xe_pcode and also ensure PCODE is initialized. ++ * xe_pcode_init: initialize components of PCODE + * @gt: gt instance + * +- * This function initializes the xe_pcode component, and when needed, it ensures +- * that PCODE has properly performed its initialization and it is really ready +- * to go. To be called once only during probe. +- * +- * It returns 0 on success, and -error number on failure. ++ * This function initializes the xe_pcode component. ++ * To be called once only during probe. + */ +-int xe_pcode_probe(struct xe_gt *gt) ++void xe_pcode_init(struct xe_gt *gt) + { + drmm_mutex_init(>_to_xe(gt)->drm, >->pcode.lock); ++} + +- if (gt_to_xe(gt)->info.skip_pcode) +- return 0; +- +- if (!IS_DGFX(gt_to_xe(gt))) +- return 0; +- +- return xe_pcode_init(gt); ++/** ++ * xe_pcode_probe_early: initializes PCODE ++ * @xe: xe instance ++ * ++ * This function checks the initialization status of PCODE ++ * To be called once only during early probe without locks. ++ * ++ * Returns 0 on success, error code otherwise ++ */ ++int xe_pcode_probe_early(struct xe_device *xe) ++{ ++ return xe_pcode_ready(xe, false); + } +diff --git a/drivers/gpu/drm/xe/xe_pcode.h b/drivers/gpu/drm/xe/xe_pcode.h +index 08cb1d047cba2..3f54c6d2a57d2 100644 +--- a/drivers/gpu/drm/xe/xe_pcode.h ++++ b/drivers/gpu/drm/xe/xe_pcode.h +@@ -8,9 +8,11 @@ + + #include <linux/types.h> + struct xe_gt; ++struct xe_device; + +-int xe_pcode_probe(struct xe_gt *gt); +-int xe_pcode_init(struct xe_gt *gt); ++void xe_pcode_init(struct xe_gt *gt); ++int xe_pcode_probe_early(struct xe_device *xe); ++int xe_pcode_ready(struct xe_device *xe, bool locked); + int xe_pcode_init_min_freq_table(struct xe_gt *gt, u32 min_gt_freq, + u32 max_gt_freq); + int xe_pcode_read(struct xe_gt *gt, u32 mbox, u32 *val, u32 *val1); +diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c +index 53b3b0b019acd..944cf4d76099e 100644 +--- a/drivers/gpu/drm/xe/xe_pm.c ++++ b/drivers/gpu/drm/xe/xe_pm.c +@@ -54,13 +54,15 @@ int xe_pm_suspend(struct xe_device *xe) + u8 id; + int err; + ++ drm_dbg(&xe->drm, "Suspending device\n"); ++ + for_each_gt(gt, xe, id) + xe_gt_suspend_prepare(gt); + + /* FIXME: Super racey... */ + err = xe_bo_evict_all(xe); + if (err) +- return err; ++ goto err; + + xe_display_pm_suspend(xe); + +@@ -68,7 +70,7 @@ int xe_pm_suspend(struct xe_device *xe) + err = xe_gt_suspend(gt); + if (err) { + xe_display_pm_resume(xe); +- return err; ++ goto err; + } + } + +@@ -76,7 +78,11 @@ int xe_pm_suspend(struct xe_device *xe) + + xe_display_pm_suspend_late(xe); + ++ drm_dbg(&xe->drm, "Device suspended\n"); + return 0; ++err: ++ drm_dbg(&xe->drm, "Device suspend failed %d\n", err); ++ return err; + } + + /** +@@ -92,14 +98,14 @@ int xe_pm_resume(struct xe_device *xe) + u8 id; + int err; + ++ drm_dbg(&xe->drm, "Resuming device\n"); ++ + for_each_tile(tile, xe, id) + xe_wa_apply_tile_workarounds(tile); + +- for_each_gt(gt, xe, id) { +- err = xe_pcode_init(gt); +- if (err) +- return err; +- } ++ err = xe_pcode_ready(xe, true); ++ if (err) ++ return err; + + xe_display_pm_resume_early(xe); + +@@ -109,7 +115,7 @@ int xe_pm_resume(struct xe_device *xe) + */ + err = xe_bo_restore_kernel(xe); + if (err) +- return err; ++ goto err; + + xe_irq_resume(xe); + +@@ -120,9 +126,13 @@ int xe_pm_resume(struct xe_device *xe) + + err = xe_bo_restore_user(xe); + if (err) +- return err; ++ goto err; + ++ drm_dbg(&xe->drm, "Device resumed\n"); + return 0; ++err: ++ drm_dbg(&xe->drm, "Device resume failed %d\n", err); ++ return err; + } + + static bool xe_pm_pci_d3cold_capable(struct xe_device *xe) +@@ -310,11 +320,9 @@ int xe_pm_runtime_resume(struct xe_device *xe) + xe->d3cold.power_lost = xe_guc_in_reset(>->uc.guc); + + if (xe->d3cold.allowed && xe->d3cold.power_lost) { +- for_each_gt(gt, xe, id) { +- err = xe_pcode_init(gt); +- if (err) +- goto out; +- } ++ err = xe_pcode_ready(xe, true); ++ if (err) ++ goto out; + + /* + * This only restores pinned memory which is the memory +diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +index 88eb33acd5f0d..face8d6b2a6fb 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +@@ -256,12 +256,12 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev) + if (ret) + goto err_dp; + ++ drm_bridge_add(dpsub->bridge); ++ + if (dpsub->dma_enabled) { + ret = zynqmp_dpsub_drm_init(dpsub); + if (ret) + goto err_disp; +- } else { +- drm_bridge_add(dpsub->bridge); + } + + dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed"); +@@ -288,9 +288,8 @@ static void zynqmp_dpsub_remove(struct platform_device *pdev) + + if (dpsub->drm) + zynqmp_dpsub_drm_cleanup(dpsub); +- else +- drm_bridge_remove(dpsub->bridge); + ++ drm_bridge_remove(dpsub->bridge); + zynqmp_disp_remove(dpsub); + zynqmp_dp_remove(dpsub); + +diff --git a/drivers/hwmon/intel-m10-bmc-hwmon.c b/drivers/hwmon/intel-m10-bmc-hwmon.c +index 6500ca548f9c7..ca2dff1589251 100644 +--- a/drivers/hwmon/intel-m10-bmc-hwmon.c ++++ b/drivers/hwmon/intel-m10-bmc-hwmon.c +@@ -429,7 +429,7 @@ static const struct m10bmc_sdata n6000bmc_curr_tbl[] = { + }; + + static const struct m10bmc_sdata n6000bmc_power_tbl[] = { +- { 0x724, 0x0, 0x0, 0x0, 0x0, 1, "Board Power" }, ++ { 0x724, 0x0, 0x0, 0x0, 0x0, 1000, "Board Power" }, + }; + + static const struct hwmon_channel_info * const n6000bmc_hinfo[] = { +diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c +index 1f96e94967ee8..439dd3dba5fc8 100644 +--- a/drivers/hwmon/shtc1.c ++++ b/drivers/hwmon/shtc1.c +@@ -238,7 +238,7 @@ static int shtc1_probe(struct i2c_client *client) + + if (np) { + data->setup.blocking_io = of_property_read_bool(np, "sensirion,blocking-io"); +- data->setup.high_precision = !of_property_read_bool(np, "sensicon,low-precision"); ++ data->setup.high_precision = !of_property_read_bool(np, "sensirion,low-precision"); + } else { + if (client->dev.platform_data) + data->setup = *(struct shtc1_platform_data *)dev->platform_data; +diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c +index c2ca4a02dfce1..a0bdfabddbc68 100644 +--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c ++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c +@@ -1240,6 +1240,8 @@ static void etm4_init_arch_data(void *info) + drvdata->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0); + /* QSUPP, bits[16:15] Q element support field */ + drvdata->q_support = FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0); ++ if (drvdata->q_support) ++ drvdata->q_filt = !!(etmidr0 & TRCIDR0_QFILT); + /* TSSIZE, bits[28:24] Global timestamp size field */ + drvdata->ts_size = FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0); + +@@ -1732,16 +1734,14 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) + state->trcccctlr = etm4x_read32(csa, TRCCCCTLR); + state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR); + state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR); +- state->trcqctlr = etm4x_read32(csa, TRCQCTLR); ++ if (drvdata->q_filt) ++ state->trcqctlr = etm4x_read32(csa, TRCQCTLR); + + state->trcvictlr = etm4x_read32(csa, TRCVICTLR); + state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR); + state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR); + if (drvdata->nr_pe_cmp) + state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR); +- state->trcvdctlr = etm4x_read32(csa, TRCVDCTLR); +- state->trcvdsacctlr = etm4x_read32(csa, TRCVDSACCTLR); +- state->trcvdarcctlr = etm4x_read32(csa, TRCVDARCCTLR); + + for (i = 0; i < drvdata->nrseqstate - 1; i++) + state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i)); +@@ -1758,7 +1758,8 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) + state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i)); + } + +- for (i = 0; i < drvdata->nr_resource * 2; i++) ++ /* Resource selector pair 0 is reserved */ ++ for (i = 2; i < drvdata->nr_resource * 2; i++) + state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i)); + + for (i = 0; i < drvdata->nr_ss_cmp; i++) { +@@ -1843,8 +1844,10 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata) + { + int i; + struct etmv4_save_state *state = drvdata->save_state; +- struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base); +- struct csdev_access *csa = &tmp_csa; ++ struct csdev_access *csa = &drvdata->csdev->access; ++ ++ if (WARN_ON(!drvdata->csdev)) ++ return; + + etm4_cs_unlock(drvdata, csa); + etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET); +@@ -1863,16 +1866,14 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata) + etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR); + etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR); + etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR); +- etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR); ++ if (drvdata->q_filt) ++ etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR); + + etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR); + etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR); + etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR); + if (drvdata->nr_pe_cmp) + etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR); +- etm4x_relaxed_write32(csa, state->trcvdctlr, TRCVDCTLR); +- etm4x_relaxed_write32(csa, state->trcvdsacctlr, TRCVDSACCTLR); +- etm4x_relaxed_write32(csa, state->trcvdarcctlr, TRCVDARCCTLR); + + for (i = 0; i < drvdata->nrseqstate - 1; i++) + etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i)); +@@ -1889,7 +1890,8 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata) + etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i)); + } + +- for (i = 0; i < drvdata->nr_resource * 2; i++) ++ /* Resource selector pair 0 is reserved */ ++ for (i = 2; i < drvdata->nr_resource * 2; i++) + etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i)); + + for (i = 0; i < drvdata->nr_ss_cmp; i++) { +@@ -2213,6 +2215,9 @@ static int etm4_probe_platform_dev(struct platform_device *pdev) + ret = etm4_probe(&pdev->dev); + + pm_runtime_put(&pdev->dev); ++ if (ret) ++ pm_runtime_disable(&pdev->dev); ++ + return ret; + } + +diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h +index 9ea678bc2e8e5..9e9165f62e81f 100644 +--- a/drivers/hwtracing/coresight/coresight-etm4x.h ++++ b/drivers/hwtracing/coresight/coresight-etm4x.h +@@ -43,9 +43,6 @@ + #define TRCVIIECTLR 0x084 + #define TRCVISSCTLR 0x088 + #define TRCVIPCSSCTLR 0x08C +-#define TRCVDCTLR 0x0A0 +-#define TRCVDSACCTLR 0x0A4 +-#define TRCVDARCCTLR 0x0A8 + /* Derived resources registers */ + #define TRCSEQEVRn(n) (0x100 + (n * 4)) /* n = 0-2 */ + #define TRCSEQRSTEVR 0x118 +@@ -90,9 +87,6 @@ + /* Address Comparator registers n = 0-15 */ + #define TRCACVRn(n) (0x400 + (n * 8)) + #define TRCACATRn(n) (0x480 + (n * 8)) +-/* Data Value Comparator Value registers, n = 0-7 */ +-#define TRCDVCVRn(n) (0x500 + (n * 16)) +-#define TRCDVCMRn(n) (0x580 + (n * 16)) + /* ContextID/Virtual ContextID comparators, n = 0-7 */ + #define TRCCIDCVRn(n) (0x600 + (n * 8)) + #define TRCVMIDCVRn(n) (0x640 + (n * 8)) +@@ -141,6 +135,7 @@ + #define TRCIDR0_TRCCCI BIT(7) + #define TRCIDR0_RETSTACK BIT(9) + #define TRCIDR0_NUMEVENT_MASK GENMASK(11, 10) ++#define TRCIDR0_QFILT BIT(14) + #define TRCIDR0_QSUPP_MASK GENMASK(16, 15) + #define TRCIDR0_TSSIZE_MASK GENMASK(28, 24) + +@@ -272,9 +267,6 @@ + /* List of registers accessible via System instructions */ + #define ETM4x_ONLY_SYSREG_LIST(op, val) \ + CASE_##op((val), TRCPROCSELR) \ +- CASE_##op((val), TRCVDCTLR) \ +- CASE_##op((val), TRCVDSACCTLR) \ +- CASE_##op((val), TRCVDARCCTLR) \ + CASE_##op((val), TRCOSLAR) + + #define ETM_COMMON_SYSREG_LIST(op, val) \ +@@ -422,22 +414,6 @@ + CASE_##op((val), TRCACATRn(13)) \ + CASE_##op((val), TRCACATRn(14)) \ + CASE_##op((val), TRCACATRn(15)) \ +- CASE_##op((val), TRCDVCVRn(0)) \ +- CASE_##op((val), TRCDVCVRn(1)) \ +- CASE_##op((val), TRCDVCVRn(2)) \ +- CASE_##op((val), TRCDVCVRn(3)) \ +- CASE_##op((val), TRCDVCVRn(4)) \ +- CASE_##op((val), TRCDVCVRn(5)) \ +- CASE_##op((val), TRCDVCVRn(6)) \ +- CASE_##op((val), TRCDVCVRn(7)) \ +- CASE_##op((val), TRCDVCMRn(0)) \ +- CASE_##op((val), TRCDVCMRn(1)) \ +- CASE_##op((val), TRCDVCMRn(2)) \ +- CASE_##op((val), TRCDVCMRn(3)) \ +- CASE_##op((val), TRCDVCMRn(4)) \ +- CASE_##op((val), TRCDVCMRn(5)) \ +- CASE_##op((val), TRCDVCMRn(6)) \ +- CASE_##op((val), TRCDVCMRn(7)) \ + CASE_##op((val), TRCCIDCVRn(0)) \ + CASE_##op((val), TRCCIDCVRn(1)) \ + CASE_##op((val), TRCCIDCVRn(2)) \ +@@ -907,9 +883,6 @@ struct etmv4_save_state { + u32 trcviiectlr; + u32 trcvissctlr; + u32 trcvipcssctlr; +- u32 trcvdctlr; +- u32 trcvdsacctlr; +- u32 trcvdarcctlr; + + u32 trcseqevr[ETM_MAX_SEQ_STATES]; + u32 trcseqrstevr; +@@ -982,6 +955,7 @@ struct etmv4_save_state { + * @os_unlock: True if access to management registers is allowed. + * @instrp0: Tracing of load and store instructions + * as P0 elements is supported. ++ * @q_filt: Q element filtering support, if Q elements are supported. + * @trcbb: Indicates if the trace unit supports branch broadcast tracing. + * @trccond: If the trace unit supports conditional + * instruction tracing. +@@ -1044,6 +1018,7 @@ struct etmv4_drvdata { + bool boot_enable; + bool os_unlock; + bool instrp0; ++ bool q_filt; + bool trcbb; + bool trccond; + bool retstack; +diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c +index 534fbefc7f6aa..20895d3915623 100644 +--- a/drivers/hwtracing/stm/core.c ++++ b/drivers/hwtracing/stm/core.c +@@ -868,8 +868,11 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data, + return -ENOMEM; + + stm->major = register_chrdev(0, stm_data->name, &stm_fops); +- if (stm->major < 0) +- goto err_free; ++ if (stm->major < 0) { ++ err = stm->major; ++ vfree(stm); ++ return err; ++ } + + device_initialize(&stm->dev); + stm->dev.devt = MKDEV(stm->major, 0); +@@ -913,10 +916,8 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data, + err_device: + unregister_chrdev(stm->major, stm_data->name); + +- /* matches device_initialize() above */ ++ /* calls stm_device_release() */ + put_device(&stm->dev); +-err_free: +- vfree(stm); + + return err; + } +diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c +index 4bb7d6756947c..2fce3e84ba646 100644 +--- a/drivers/i2c/busses/i2c-cadence.c ++++ b/drivers/i2c/busses/i2c-cadence.c +@@ -633,6 +633,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) + + if (hold_clear) { + ctrl_reg &= ~CDNS_I2C_CR_HOLD; ++ ctrl_reg &= ~CDNS_I2C_CR_CLR_FIFO; + /* + * In case of Xilinx Zynq SOC, clear the HOLD bit before transfer size + * register reaches '0'. This is an IP bug which causes transfer size +diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c +index bbea521b05dda..a73f5bb9a1645 100644 +--- a/drivers/i2c/busses/i2c-synquacer.c ++++ b/drivers/i2c/busses/i2c-synquacer.c +@@ -550,17 +550,13 @@ static int synquacer_i2c_probe(struct platform_device *pdev) + device_property_read_u32(&pdev->dev, "socionext,pclk-rate", + &i2c->pclkrate); + +- i2c->pclk = devm_clk_get(&pdev->dev, "pclk"); +- if (PTR_ERR(i2c->pclk) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- if (!IS_ERR_OR_NULL(i2c->pclk)) { +- dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk); +- +- ret = clk_prepare_enable(i2c->pclk); +- if (ret) +- return dev_err_probe(&pdev->dev, ret, "failed to enable clock\n"); +- i2c->pclkrate = clk_get_rate(i2c->pclk); +- } ++ i2c->pclk = devm_clk_get_enabled(&pdev->dev, "pclk"); ++ if (IS_ERR(i2c->pclk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(i2c->pclk), ++ "failed to get and enable clock\n"); ++ ++ dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk); ++ i2c->pclkrate = clk_get_rate(i2c->pclk); + + if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE || + i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE) +@@ -615,8 +611,6 @@ static void synquacer_i2c_remove(struct platform_device *pdev) + struct synquacer_i2c *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adapter); +- if (!IS_ERR(i2c->pclk)) +- clk_disable_unprepare(i2c->pclk); + }; + + static const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = { +diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c +index 5ee4db68988e2..a2298ab460a37 100644 +--- a/drivers/i3c/master/svc-i3c-master.c ++++ b/drivers/i3c/master/svc-i3c-master.c +@@ -1080,7 +1080,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, + * and yield the above events handler. + */ + if (SVC_I3C_MSTATUS_IBIWON(reg)) { +- ret = -ENXIO; ++ ret = -EAGAIN; + *actual_len = 0; + goto emit_stop; + } +diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c +index 4156639b3c8bd..a543b91124b07 100644 +--- a/drivers/iio/adc/adi-axi-adc.c ++++ b/drivers/iio/adc/adi-axi-adc.c +@@ -207,9 +207,9 @@ static int adi_axi_adc_probe(struct platform_device *pdev) + if (ret) + return ret; + +- if (*expected_ver > ver) { ++ if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) { + dev_err(&pdev->dev, +- "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n", ++ "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n", + ADI_AXI_PCORE_VER_MAJOR(*expected_ver), + ADI_AXI_PCORE_VER_MINOR(*expected_ver), + ADI_AXI_PCORE_VER_PATCH(*expected_ver), +diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c +index e0c2742da5236..8a0c357422121 100644 +--- a/drivers/iio/adc/pac1934.c ++++ b/drivers/iio/adc/pac1934.c +@@ -787,6 +787,15 @@ static int pac1934_read_raw(struct iio_dev *indio_dev, + s64 curr_energy; + int ret, channel = chan->channel - 1; + ++ /* ++ * For AVG the index should be between 5 to 8. ++ * To calculate PAC1934_CH_VOLTAGE_AVERAGE, ++ * respectively PAC1934_CH_CURRENT real index, we need ++ * to remove the added offset (PAC1934_MAX_NUM_CHANNELS). ++ */ ++ if (channel >= PAC1934_MAX_NUM_CHANNELS) ++ channel = channel - PAC1934_MAX_NUM_CHANNELS; ++ + ret = pac1934_retrieve_data(info, PAC1934_MIN_UPDATE_WAIT_TIME_US); + if (ret < 0) + return ret; +diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c +index b5d3c9cea5c4e..283c207571064 100644 +--- a/drivers/iio/adc/stm32-adc.c ++++ b/drivers/iio/adc/stm32-adc.c +@@ -2234,6 +2234,7 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev, + if (vin[0] != val || vin[1] >= adc_info->max_channels) { + dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n", + vin[0], vin[1]); ++ ret = -EINVAL; + goto err; + } + } else if (ret != -EINVAL) { +diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c +index 4302093b92c75..8684ba246969b 100644 +--- a/drivers/iio/industrialio-core.c ++++ b/drivers/iio/industrialio-core.c +@@ -1654,8 +1654,10 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) + return NULL; + + indio_dev = &iio_dev_opaque->indio_dev; +- indio_dev->priv = (char *)iio_dev_opaque + +- ALIGN(sizeof(struct iio_dev_opaque), IIO_DMA_MINALIGN); ++ ++ if (sizeof_priv) ++ indio_dev->priv = (char *)iio_dev_opaque + ++ ALIGN(sizeof(*iio_dev_opaque), IIO_DMA_MINALIGN); + + indio_dev->dev.parent = parent; + indio_dev->dev.type = &iio_device_type; +diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c +index 1ff091b2f764d..d0a516d56da47 100644 +--- a/drivers/iio/pressure/dps310.c ++++ b/drivers/iio/pressure/dps310.c +@@ -730,7 +730,7 @@ static int dps310_read_pressure(struct dps310_data *data, int *val, int *val2, + } + } + +-static int dps310_calculate_temp(struct dps310_data *data) ++static int dps310_calculate_temp(struct dps310_data *data, int *val) + { + s64 c0; + s64 t; +@@ -746,7 +746,9 @@ static int dps310_calculate_temp(struct dps310_data *data) + t = c0 + ((s64)data->temp_raw * (s64)data->c1); + + /* Convert to milliCelsius and scale the temperature */ +- return (int)div_s64(t * 1000LL, kt); ++ *val = (int)div_s64(t * 1000LL, kt); ++ ++ return 0; + } + + static int dps310_read_temp(struct dps310_data *data, int *val, int *val2, +@@ -768,11 +770,10 @@ static int dps310_read_temp(struct dps310_data *data, int *val, int *val2, + if (rc) + return rc; + +- rc = dps310_calculate_temp(data); +- if (rc < 0) ++ rc = dps310_calculate_temp(data, val); ++ if (rc) + return rc; + +- *val = rc; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: +diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c +index f253295795f0a..be0743dac3fff 100644 +--- a/drivers/infiniband/core/addr.c ++++ b/drivers/infiniband/core/addr.c +@@ -348,16 +348,10 @@ static int dst_fetch_ha(const struct dst_entry *dst, + + static bool has_gateway(const struct dst_entry *dst, sa_family_t family) + { +- struct rtable *rt; +- struct rt6_info *rt6; +- +- if (family == AF_INET) { +- rt = container_of(dst, struct rtable, dst); +- return rt->rt_uses_gateway; +- } ++ if (family == AF_INET) ++ return dst_rtable(dst)->rt_uses_gateway; + +- rt6 = container_of(dst, struct rt6_info, dst); +- return rt6->rt6i_flags & RTF_GATEWAY; ++ return dst_rt6_info(dst)->rt6i_flags & RTF_GATEWAY; + } + + static int fetch_ha(const struct dst_entry *dst, struct rdma_dev_addr *dev_addr, +diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c +index 6e8cc28debd97..80d16c92a08b3 100644 +--- a/drivers/input/misc/ims-pcu.c ++++ b/drivers/input/misc/ims-pcu.c +@@ -42,8 +42,8 @@ struct ims_pcu_backlight { + #define IMS_PCU_PART_NUMBER_LEN 15 + #define IMS_PCU_SERIAL_NUMBER_LEN 8 + #define IMS_PCU_DOM_LEN 8 +-#define IMS_PCU_FW_VERSION_LEN (9 + 1) +-#define IMS_PCU_BL_VERSION_LEN (9 + 1) ++#define IMS_PCU_FW_VERSION_LEN 16 ++#define IMS_PCU_BL_VERSION_LEN 16 + #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) + + #define IMS_PCU_PCU_B_DEVICE_ID 5 +diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c +index 5c288fe7accf1..79f478d3a9b37 100644 +--- a/drivers/input/misc/pm8xxx-vibrator.c ++++ b/drivers/input/misc/pm8xxx-vibrator.c +@@ -13,7 +13,8 @@ + + #define VIB_MAX_LEVEL_mV (3100) + #define VIB_MIN_LEVEL_mV (1200) +-#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV) ++#define VIB_PER_STEP_mV (100) ++#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV + VIB_PER_STEP_mV) + + #define MAX_FF_SPEED 0xff + +@@ -117,10 +118,10 @@ static void pm8xxx_work_handler(struct work_struct *work) + vib->active = true; + vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) + + VIB_MIN_LEVEL_mV; +- vib->level /= 100; ++ vib->level /= VIB_PER_STEP_mV; + } else { + vib->active = false; +- vib->level = VIB_MIN_LEVEL_mV / 100; ++ vib->level = VIB_MIN_LEVEL_mV / VIB_PER_STEP_mV; + } + + pm8xxx_vib_set(vib, vib->active); +diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c +index 5979deabe23d1..256f757a13267 100644 +--- a/drivers/input/mouse/cyapa.c ++++ b/drivers/input/mouse/cyapa.c +@@ -1347,10 +1347,16 @@ static int cyapa_suspend(struct device *dev) + u8 power_mode; + int error; + +- error = mutex_lock_interruptible(&cyapa->state_sync_lock); ++ error = mutex_lock_interruptible(&cyapa->input->mutex); + if (error) + return error; + ++ error = mutex_lock_interruptible(&cyapa->state_sync_lock); ++ if (error) { ++ mutex_unlock(&cyapa->input->mutex); ++ return error; ++ } ++ + /* + * Runtime PM is enable only when device is in operational mode and + * users in use, so need check it before disable it to +@@ -1385,6 +1391,8 @@ static int cyapa_suspend(struct device *dev) + cyapa->irq_wake = (enable_irq_wake(client->irq) == 0); + + mutex_unlock(&cyapa->state_sync_lock); ++ mutex_unlock(&cyapa->input->mutex); ++ + return 0; + } + +@@ -1394,6 +1402,7 @@ static int cyapa_resume(struct device *dev) + struct cyapa *cyapa = i2c_get_clientdata(client); + int error; + ++ mutex_lock(&cyapa->input->mutex); + mutex_lock(&cyapa->state_sync_lock); + + if (device_may_wakeup(dev) && cyapa->irq_wake) { +@@ -1412,6 +1421,7 @@ static int cyapa_resume(struct device *dev) + enable_irq(client->irq); + + mutex_unlock(&cyapa->state_sync_lock); ++ mutex_unlock(&cyapa->input->mutex); + return 0; + } + +diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c +index 50552dc7b4f5e..676b0bda3d720 100644 +--- a/drivers/input/serio/ioc3kbd.c ++++ b/drivers/input/serio/ioc3kbd.c +@@ -200,9 +200,16 @@ static void ioc3kbd_remove(struct platform_device *pdev) + serio_unregister_port(d->aux); + } + ++static const struct platform_device_id ioc3kbd_id_table[] = { ++ { "ioc3-kbd", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(platform, ioc3kbd_id_table); ++ + static struct platform_driver ioc3kbd_driver = { + .probe = ioc3kbd_probe, + .remove_new = ioc3kbd_remove, ++ .id_table = ioc3kbd_id_table, + .driver = { + .name = "ioc3-kbd", + }, +diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c +index 96735800b13c0..ba4cc08684d63 100644 +--- a/drivers/interconnect/qcom/qcm2290.c ++++ b/drivers/interconnect/qcom/qcm2290.c +@@ -164,7 +164,7 @@ static struct qcom_icc_node mas_snoc_bimc = { + .name = "mas_snoc_bimc", + .buswidth = 16, + .qos.ap_owned = true, +- .qos.qos_port = 2, ++ .qos.qos_port = 6, + .qos.qos_mode = NOC_QOS_MODE_BYPASS, + .mas_rpm_id = 164, + .slv_rpm_id = -1, +diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c +index 4e3936a39d0ed..e1b414b403534 100644 +--- a/drivers/leds/leds-pwm.c ++++ b/drivers/leds/leds-pwm.c +@@ -53,7 +53,13 @@ static int led_pwm_set(struct led_classdev *led_cdev, + duty = led_dat->pwmstate.period - duty; + + led_dat->pwmstate.duty_cycle = duty; +- led_dat->pwmstate.enabled = true; ++ /* ++ * Disabling a PWM doesn't guarantee that it emits the inactive level. ++ * So keep it on. Only for suspending the PWM should be disabled because ++ * otherwise it refuses to suspend. The possible downside is that the ++ * LED might stay (or even go) on. ++ */ ++ led_dat->pwmstate.enabled = !(led_cdev->flags & LED_SUSPENDED); + return pwm_apply_might_sleep(led_dat->pwm, &led_dat->pwmstate); + } + +diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c +index ead2200f39ba0..033aff11f87cf 100644 +--- a/drivers/mailbox/mtk-cmdq-mailbox.c ++++ b/drivers/mailbox/mtk-cmdq-mailbox.c +@@ -465,7 +465,7 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan) + struct cmdq_task *task, *tmp; + unsigned long flags; + +- WARN_ON(pm_runtime_get_sync(cmdq->mbox.dev)); ++ WARN_ON(pm_runtime_get_sync(cmdq->mbox.dev) < 0); + + spin_lock_irqsave(&thread->chan->lock, flags); + if (list_empty(&thread->task_busy_list)) +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 559a172ebc6cb..da09834990b87 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -490,6 +490,15 @@ int cec_thread_func(void *_adap) + goto unlock; + } + ++ if (adap->transmit_in_progress && ++ adap->transmit_in_progress_aborted) { ++ if (adap->transmitting) ++ cec_data_cancel(adap->transmitting, ++ CEC_TX_STATUS_ABORTED, 0); ++ adap->transmit_in_progress = false; ++ adap->transmit_in_progress_aborted = false; ++ goto unlock; ++ } + if (adap->transmit_in_progress && timeout) { + /* + * If we timeout, then log that. Normally this does +@@ -771,6 +780,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + { + struct cec_data *data; + bool is_raw = msg_is_raw(msg); ++ int err; + + if (adap->devnode.unregistered) + return -ENODEV; +@@ -935,11 +945,13 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + * Release the lock and wait, retake the lock afterwards. + */ + mutex_unlock(&adap->lock); +- wait_for_completion_killable(&data->c); +- if (!data->completed) +- cancel_delayed_work_sync(&data->work); ++ err = wait_for_completion_killable(&data->c); ++ cancel_delayed_work_sync(&data->work); + mutex_lock(&adap->lock); + ++ if (err) ++ adap->transmit_in_progress_aborted = true; ++ + /* Cancel the transmit if it was interrupted */ + if (!data->completed) { + if (data->msg.tx_status & CEC_TX_STATUS_OK) +@@ -1575,9 +1587,12 @@ static int cec_config_thread_func(void *arg) + */ + static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) + { +- if (WARN_ON(adap->is_configuring || adap->is_configured)) ++ if (WARN_ON(adap->is_claiming_log_addrs || ++ adap->is_configuring || adap->is_configured)) + return; + ++ adap->is_claiming_log_addrs = true; ++ + init_completion(&adap->config_completion); + + /* Ready to kick off the thread */ +@@ -1592,6 +1607,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) + wait_for_completion(&adap->config_completion); + mutex_lock(&adap->lock); + } ++ adap->is_claiming_log_addrs = false; + } + + /* +diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c +index 67dc79ef17050..3ef9153443044 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -178,7 +178,7 @@ static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh, + CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU | + CEC_LOG_ADDRS_FL_CDC_ONLY; + mutex_lock(&adap->lock); +- if (!adap->is_configuring && ++ if (!adap->is_claiming_log_addrs && !adap->is_configuring && + (!log_addrs.num_log_addrs || !adap->is_configured) && + !cec_is_busy(adap, fh)) { + err = __cec_s_log_addrs(adap, &log_addrs, block); +@@ -664,6 +664,8 @@ static int cec_release(struct inode *inode, struct file *filp) + list_del_init(&data->xfer_list); + } + mutex_unlock(&adap->lock); ++ ++ mutex_lock(&fh->lock); + while (!list_empty(&fh->msgs)) { + struct cec_msg_entry *entry = + list_first_entry(&fh->msgs, struct cec_msg_entry, list); +@@ -681,6 +683,7 @@ static int cec_release(struct inode *inode, struct file *filp) + kfree(entry); + } + } ++ mutex_unlock(&fh->lock); + kfree(fh); + + cec_put_device(devnode); +diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c +index 39d321e2b7f98..4577a8977c85a 100644 +--- a/drivers/media/i2c/ov2680.c ++++ b/drivers/media/i2c/ov2680.c +@@ -1116,25 +1116,24 @@ static int ov2680_parse_dt(struct ov2680_dev *sensor) + sensor->pixel_rate = sensor->link_freq[0] * 2; + do_div(sensor->pixel_rate, 10); + +- /* Verify bus cfg */ +- if (bus_cfg.bus.mipi_csi2.num_data_lanes != 1) { +- ret = dev_err_probe(dev, -EINVAL, +- "only a 1-lane CSI2 config is supported"); +- goto out_free_bus_cfg; ++ if (!bus_cfg.nr_of_link_frequencies) { ++ dev_warn(dev, "Consider passing 'link-frequencies' in DT\n"); ++ goto skip_link_freq_validation; + } + + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) + if (bus_cfg.link_frequencies[i] == sensor->link_freq[0]) + break; + +- if (bus_cfg.nr_of_link_frequencies == 0 || +- bus_cfg.nr_of_link_frequencies == i) { ++ if (bus_cfg.nr_of_link_frequencies == i) { + ret = dev_err_probe(dev, -EINVAL, + "supported link freq %lld not found\n", + sensor->link_freq[0]); + goto out_free_bus_cfg; + } + ++skip_link_freq_validation: ++ ret = 0; + out_free_bus_cfg: + v4l2_fwnode_endpoint_free(&bus_cfg); + return ret; +diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.c +index a22b7dfc656e1..1a2b14a3e219c 100644 +--- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.c ++++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.c +@@ -58,13 +58,15 @@ int mtk_vcodec_init_enc_clk(struct mtk_vcodec_enc_dev *mtkdev) + return 0; + } + +-void mtk_vcodec_enc_pw_on(struct mtk_vcodec_pm *pm) ++int mtk_vcodec_enc_pw_on(struct mtk_vcodec_pm *pm) + { + int ret; + + ret = pm_runtime_resume_and_get(pm->dev); + if (ret) + dev_err(pm->dev, "pm_runtime_resume_and_get fail: %d", ret); ++ ++ return ret; + } + + void mtk_vcodec_enc_pw_off(struct mtk_vcodec_pm *pm) +diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.h b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.h +index 157ea08ba9e36..2e28f25e36cc4 100644 +--- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.h ++++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_pm.h +@@ -10,7 +10,7 @@ + #include "mtk_vcodec_enc_drv.h" + + int mtk_vcodec_init_enc_clk(struct mtk_vcodec_enc_dev *dev); +-void mtk_vcodec_enc_pw_on(struct mtk_vcodec_pm *pm); ++int mtk_vcodec_enc_pw_on(struct mtk_vcodec_pm *pm); + void mtk_vcodec_enc_pw_off(struct mtk_vcodec_pm *pm); + void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm); + void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm); +diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.c b/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.c +index c402a686f3cb2..e83747b8d69ab 100644 +--- a/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.c ++++ b/drivers/media/platform/mediatek/vcodec/encoder/venc_drv_if.c +@@ -64,7 +64,9 @@ int venc_if_encode(struct mtk_vcodec_enc_ctx *ctx, + ctx->dev->curr_ctx = ctx; + spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + +- mtk_vcodec_enc_pw_on(&ctx->dev->pm); ++ ret = mtk_vcodec_enc_pw_on(&ctx->dev->pm); ++ if (ret) ++ goto venc_if_encode_pw_on_err; + mtk_vcodec_enc_clock_on(&ctx->dev->pm); + ret = ctx->enc_if->encode(ctx->drv_handle, opt, frm_buf, + bs_buf, result); +@@ -75,6 +77,7 @@ int venc_if_encode(struct mtk_vcodec_enc_ctx *ctx, + ctx->dev->curr_ctx = NULL; + spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + ++venc_if_encode_pw_on_err: + mtk_venc_unlock(ctx); + return ret; + } +diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig +index 47a8c0fb7eb9f..99c401e653bc4 100644 +--- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig ++++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig +@@ -8,6 +8,7 @@ config VIDEO_SUN8I_A83T_MIPI_CSI2 + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + select REGMAP_MMIO ++ select GENERIC_PHY + select GENERIC_PHY_MIPI_DPHY + help + Support for the Allwinner A83T MIPI CSI-2 controller and D-PHY. +diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c +index 6da83d0cffaae..22442fce76078 100644 +--- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c ++++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c +@@ -786,15 +786,14 @@ static void ti_csi2rx_buffer_queue(struct vb2_buffer *vb) + dev_warn(csi->dev, + "Failed to drain DMA. Next frame might be bogus\n"); + ++ spin_lock_irqsave(&dma->lock, flags); + ret = ti_csi2rx_start_dma(csi, buf); + if (ret) { +- dev_err(csi->dev, "Failed to start DMA: %d\n", ret); +- spin_lock_irqsave(&dma->lock, flags); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + dma->state = TI_CSI2RX_DMA_IDLE; + spin_unlock_irqrestore(&dma->lock, flags); ++ dev_err(csi->dev, "Failed to start DMA: %d\n", ret); + } else { +- spin_lock_irqsave(&dma->lock, flags); + list_add_tail(&buf->list, &dma->submitted); + spin_unlock_irqrestore(&dma->lock, flags); + } +diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c +index 790787f0eba84..bcb24d8964981 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -515,7 +515,7 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb) + + alt = fc_usb->uintf->cur_altsetting; + +- if (alt->desc.bNumEndpoints < 1) ++ if (alt->desc.bNumEndpoints < 2) + return -ENODEV; + if (!usb_endpoint_is_isoc_in(&alt->endpoint[0].desc)) + return -ENODEV; +diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c +index 366f0e4a5dc0d..e79c45db60ab5 100644 +--- a/drivers/media/usb/stk1160/stk1160-video.c ++++ b/drivers/media/usb/stk1160/stk1160-video.c +@@ -99,7 +99,7 @@ void stk1160_buffer_done(struct stk1160 *dev) + static inline + void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) + { +- int linesdone, lineoff, lencopy; ++ int linesdone, lineoff, lencopy, offset; + int bytesperline = dev->width * 2; + struct stk1160_buffer *buf = dev->isoc_ctl.buf; + u8 *dst = buf->mem; +@@ -139,8 +139,13 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) + * Check if we have enough space left in the buffer. + * In that case, we force loop exit after copy. + */ +- if (lencopy > buf->bytesused - buf->length) { +- lencopy = buf->bytesused - buf->length; ++ offset = dst - (u8 *)buf->mem; ++ if (offset > buf->length) { ++ dev_warn_ratelimited(dev->dev, "out of bounds offset\n"); ++ return; ++ } ++ if (lencopy > buf->length - offset) { ++ lencopy = buf->length - offset; + remain = lencopy; + } + +@@ -182,8 +187,13 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) + * Check if we have enough space left in the buffer. + * In that case, we force loop exit after copy. + */ +- if (lencopy > buf->bytesused - buf->length) { +- lencopy = buf->bytesused - buf->length; ++ offset = dst - (u8 *)buf->mem; ++ if (offset > buf->length) { ++ dev_warn_ratelimited(dev->dev, "offset out of bounds\n"); ++ return; ++ } ++ if (lencopy > buf->length - offset) { ++ lencopy = buf->length - offset; + remain = lencopy; + } + +diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c +index 45836f0a2b0a7..19d20871afefa 100644 +--- a/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/drivers/media/v4l2-core/v4l2-subdev.c +@@ -412,15 +412,6 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable) + if (WARN_ON(!!sd->enabled_streams == !!enable)) + return 0; + +-#if IS_REACHABLE(CONFIG_LEDS_CLASS) +- if (!IS_ERR_OR_NULL(sd->privacy_led)) { +- if (enable) +- led_set_brightness(sd->privacy_led, +- sd->privacy_led->max_brightness); +- else +- led_set_brightness(sd->privacy_led, 0); +- } +-#endif + ret = sd->ops->video->s_stream(sd, enable); + + if (!enable && ret < 0) { +@@ -428,9 +419,20 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable) + ret = 0; + } + +- if (!ret) ++ if (!ret) { + sd->enabled_streams = enable ? BIT(0) : 0; + ++#if IS_REACHABLE(CONFIG_LEDS_CLASS) ++ if (!IS_ERR_OR_NULL(sd->privacy_led)) { ++ if (enable) ++ led_set_brightness(sd->privacy_led, ++ sd->privacy_led->max_brightness); ++ else ++ led_set_brightness(sd->privacy_led, 0); ++ } ++#endif ++ } ++ + return ret; + } + +diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c +index 4f8d962bb5b2a..1300ccab3d21b 100644 +--- a/drivers/misc/vmw_vmci/vmci_guest.c ++++ b/drivers/misc/vmw_vmci/vmci_guest.c +@@ -625,7 +625,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, + if (!vmci_dev) { + dev_err(&pdev->dev, + "Can't allocate memory for VMCI device\n"); +- return -ENOMEM; ++ error = -ENOMEM; ++ goto err_unmap_mmio_base; + } + + vmci_dev->dev = &pdev->dev; +@@ -642,7 +643,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, + if (!vmci_dev->tx_buffer) { + dev_err(&pdev->dev, + "Can't allocate memory for datagram tx buffer\n"); +- return -ENOMEM; ++ error = -ENOMEM; ++ goto err_unmap_mmio_base; + } + + vmci_dev->data_buffer = dma_alloc_coherent(&pdev->dev, VMCI_DMA_DG_BUFFER_SIZE, +@@ -893,6 +895,10 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, + err_free_data_buffers: + vmci_free_dg_buffers(vmci_dev); + ++err_unmap_mmio_base: ++ if (mmio_base != NULL) ++ pci_iounmap(pdev, mmio_base); ++ + /* The rest are managed resources and will be freed by PCI core */ + return error; + } +diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +index d659c59422e1e..562034af653eb 100644 +--- a/drivers/mmc/host/sdhci_am654.c ++++ b/drivers/mmc/host/sdhci_am654.c +@@ -143,16 +143,24 @@ struct sdhci_am654_data { + struct regmap *base; + int otap_del_sel[ARRAY_SIZE(td)]; + int itap_del_sel[ARRAY_SIZE(td)]; ++ u32 itap_del_ena[ARRAY_SIZE(td)]; + int clkbuf_sel; + int trm_icp; + int drv_strength; + int strb_sel; + u32 flags; + u32 quirks; ++ bool dll_enable; + + #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) + }; + ++struct window { ++ u8 start; ++ u8 end; ++ u8 length; ++}; ++ + struct sdhci_am654_driver_data { + const struct sdhci_pltfm_data *pdata; + u32 flags; +@@ -232,11 +240,13 @@ static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock) + } + + static void sdhci_am654_write_itapdly(struct sdhci_am654_data *sdhci_am654, +- u32 itapdly) ++ u32 itapdly, u32 enable) + { + /* Set ITAPCHGWIN before writing to ITAPDLY */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, + 1 << ITAPCHGWIN_SHIFT); ++ regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, ++ enable << ITAPDLYENA_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYSEL_MASK, + itapdly << ITAPDLYSEL_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); +@@ -253,8 +263,8 @@ static void sdhci_am654_setup_delay_chain(struct sdhci_am654_data *sdhci_am654, + mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK; + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); + +- sdhci_am654_write_itapdly(sdhci_am654, +- sdhci_am654->itap_del_sel[timing]); ++ sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], ++ sdhci_am654->itap_del_ena[timing]); + } + + static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) +@@ -263,7 +273,6 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + unsigned char timing = host->mmc->ios.timing; + u32 otap_del_sel; +- u32 otap_del_ena; + u32 mask, val; + + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); +@@ -272,10 +281,9 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + + /* Setup DLL Output TAP delay */ + otap_del_sel = sdhci_am654->otap_del_sel[timing]; +- otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; +- val = (otap_del_ena << OTAPDLYENA_SHIFT) | ++ val = (0x1 << OTAPDLYENA_SHIFT) | + (otap_del_sel << OTAPDLYSEL_SHIFT); + + /* Write to STRBSEL for HS400 speed mode */ +@@ -290,10 +298,21 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) + + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); + +- if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) ++ if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) { + sdhci_am654_setup_dll(host, clock); +- else ++ sdhci_am654->dll_enable = true; ++ ++ if (timing == MMC_TIMING_MMC_HS400) { ++ sdhci_am654->itap_del_ena[timing] = 0x1; ++ sdhci_am654->itap_del_sel[timing] = sdhci_am654->itap_del_sel[timing - 1]; ++ } ++ ++ sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], ++ sdhci_am654->itap_del_ena[timing]); ++ } else { + sdhci_am654_setup_delay_chain(sdhci_am654, timing); ++ sdhci_am654->dll_enable = false; ++ } + + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, + sdhci_am654->clkbuf_sel); +@@ -306,6 +325,8 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + unsigned char timing = host->mmc->ios.timing; + u32 otap_del_sel; ++ u32 itap_del_ena; ++ u32 itap_del_sel; + u32 mask, val; + + /* Setup DLL Output TAP delay */ +@@ -314,8 +335,19 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; + val = (0x1 << OTAPDLYENA_SHIFT) | + (otap_del_sel << OTAPDLYSEL_SHIFT); +- regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); + ++ /* Setup Input TAP delay */ ++ itap_del_ena = sdhci_am654->itap_del_ena[timing]; ++ itap_del_sel = sdhci_am654->itap_del_sel[timing]; ++ ++ mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK; ++ val |= (itap_del_ena << ITAPDLYENA_SHIFT) | ++ (itap_del_sel << ITAPDLYSEL_SHIFT); ++ ++ regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, ++ 1 << ITAPCHGWIN_SHIFT); ++ regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); ++ regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, + sdhci_am654->clkbuf_sel); + +@@ -408,40 +440,105 @@ static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask) + return 0; + } + +-#define ITAP_MAX 32 ++#define ITAPDLY_LENGTH 32 ++#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1) ++ ++static u32 sdhci_am654_calculate_itap(struct sdhci_host *host, struct window ++ *fail_window, u8 num_fails, bool circular_buffer) ++{ ++ u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0; ++ u8 first_fail_start = 0, last_fail_end = 0; ++ struct device *dev = mmc_dev(host->mmc); ++ struct window pass_window = {0, 0, 0}; ++ int prev_fail_end = -1; ++ u8 i; ++ ++ if (!num_fails) ++ return ITAPDLY_LAST_INDEX >> 1; ++ ++ if (fail_window->length == ITAPDLY_LENGTH) { ++ dev_err(dev, "No passing ITAPDLY, return 0\n"); ++ return 0; ++ } ++ ++ first_fail_start = fail_window->start; ++ last_fail_end = fail_window[num_fails - 1].end; ++ ++ for (i = 0; i < num_fails; i++) { ++ start_fail = fail_window[i].start; ++ end_fail = fail_window[i].end; ++ pass_length = start_fail - (prev_fail_end + 1); ++ ++ if (pass_length > pass_window.length) { ++ pass_window.start = prev_fail_end + 1; ++ pass_window.length = pass_length; ++ } ++ prev_fail_end = end_fail; ++ } ++ ++ if (!circular_buffer) ++ pass_length = ITAPDLY_LAST_INDEX - last_fail_end; ++ else ++ pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start; ++ ++ if (pass_length > pass_window.length) { ++ pass_window.start = last_fail_end + 1; ++ pass_window.length = pass_length; ++ } ++ ++ if (!circular_buffer) ++ itap = pass_window.start + (pass_window.length >> 1); ++ else ++ itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH; ++ ++ return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap; ++} ++ + static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, + u32 opcode) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); +- int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len; +- u32 itap; ++ unsigned char timing = host->mmc->ios.timing; ++ struct window fail_window[ITAPDLY_LENGTH]; ++ u8 curr_pass, itap; ++ u8 fail_index = 0; ++ u8 prev_pass = 1; ++ ++ memset(fail_window, 0, sizeof(fail_window)); + + /* Enable ITAPDLY */ +- regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, +- 1 << ITAPDLYENA_SHIFT); ++ sdhci_am654->itap_del_ena[timing] = 0x1; ++ ++ for (itap = 0; itap < ITAPDLY_LENGTH; itap++) { ++ sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); + +- for (itap = 0; itap < ITAP_MAX; itap++) { +- sdhci_am654_write_itapdly(sdhci_am654, itap); ++ curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL); + +- cur_val = !mmc_send_tuning(host->mmc, opcode, NULL); +- if (cur_val && !prev_val) +- pass_window = itap; ++ if (!curr_pass && prev_pass) ++ fail_window[fail_index].start = itap; + +- if (!cur_val) +- fail_len++; ++ if (!curr_pass) { ++ fail_window[fail_index].end = itap; ++ fail_window[fail_index].length++; ++ } ++ ++ if (curr_pass && !prev_pass) ++ fail_index++; + +- prev_val = cur_val; ++ prev_pass = curr_pass; + } +- /* +- * Having determined the length of the failing window and start of +- * the passing window calculate the length of the passing window and +- * set the final value halfway through it considering the range as a +- * circular buffer +- */ +- pass_len = ITAP_MAX - fail_len; +- itap = (pass_window + (pass_len >> 1)) % ITAP_MAX; +- sdhci_am654_write_itapdly(sdhci_am654, itap); ++ ++ if (fail_window[fail_index].length != 0) ++ fail_index++; ++ ++ itap = sdhci_am654_calculate_itap(host, fail_window, fail_index, ++ sdhci_am654->dll_enable); ++ ++ sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); ++ ++ /* Save ITAPDLY */ ++ sdhci_am654->itap_del_sel[timing] = itap; + + return 0; + } +@@ -590,9 +687,12 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host, + host->mmc->caps2 &= ~td[i].capability; + } + +- if (td[i].itap_binding) +- device_property_read_u32(dev, td[i].itap_binding, +- &sdhci_am654->itap_del_sel[i]); ++ if (td[i].itap_binding) { ++ ret = device_property_read_u32(dev, td[i].itap_binding, ++ &sdhci_am654->itap_del_sel[i]); ++ if (!ret) ++ sdhci_am654->itap_del_ena[i] = 0x1; ++ } + } + + return 0; +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index 7cab36f94782e..db55ffdb5792d 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -48,7 +48,9 @@ obj-$(CONFIG_MHI_NET) += mhi_net.o + obj-$(CONFIG_ARCNET) += arcnet/ + obj-$(CONFIG_CAIF) += caif/ + obj-$(CONFIG_CAN) += can/ +-obj-$(CONFIG_NET_DSA) += dsa/ ++ifdef CONFIG_NET_DSA ++obj-y += dsa/ ++endif + obj-$(CONFIG_ETHERNET) += ethernet/ + obj-$(CONFIG_FDDI) += fddi/ + obj-$(CONFIG_HIPPI) += hippi/ +diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c +index 2b510f150dd88..2a5861a88d0e6 100644 +--- a/drivers/net/dsa/microchip/ksz_common.c ++++ b/drivers/net/dsa/microchip/ksz_common.c +@@ -3050,7 +3050,7 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit) + else + interface = PHY_INTERFACE_MODE_MII; + } else if (val == bitval[P_RMII_SEL]) { +- interface = PHY_INTERFACE_MODE_RGMII; ++ interface = PHY_INTERFACE_MODE_RMII; + } else { + interface = PHY_INTERFACE_MODE_RGMII; + if (data8 & P_RGMII_ID_EG_ENABLE) +diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c +index 2d8a66ea82fab..713a595370bff 100644 +--- a/drivers/net/ethernet/amazon/ena/ena_com.c ++++ b/drivers/net/ethernet/amazon/ena/ena_com.c +@@ -312,7 +312,6 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev, + struct ena_com_io_sq *io_sq) + { + size_t size; +- int dev_node = 0; + + memset(&io_sq->desc_addr, 0x0, sizeof(io_sq->desc_addr)); + +@@ -325,12 +324,9 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev, + size = io_sq->desc_entry_size * io_sq->q_depth; + + if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST) { +- dev_node = dev_to_node(ena_dev->dmadev); +- set_dev_node(ena_dev->dmadev, ctx->numa_node); + io_sq->desc_addr.virt_addr = + dma_alloc_coherent(ena_dev->dmadev, size, &io_sq->desc_addr.phys_addr, + GFP_KERNEL); +- set_dev_node(ena_dev->dmadev, dev_node); + if (!io_sq->desc_addr.virt_addr) { + io_sq->desc_addr.virt_addr = + dma_alloc_coherent(ena_dev->dmadev, size, +@@ -354,10 +350,7 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev, + size = (size_t)io_sq->bounce_buf_ctrl.buffer_size * + io_sq->bounce_buf_ctrl.buffers_num; + +- dev_node = dev_to_node(ena_dev->dmadev); +- set_dev_node(ena_dev->dmadev, ctx->numa_node); + io_sq->bounce_buf_ctrl.base_buffer = devm_kzalloc(ena_dev->dmadev, size, GFP_KERNEL); +- set_dev_node(ena_dev->dmadev, dev_node); + if (!io_sq->bounce_buf_ctrl.base_buffer) + io_sq->bounce_buf_ctrl.base_buffer = + devm_kzalloc(ena_dev->dmadev, size, GFP_KERNEL); +@@ -397,7 +390,6 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev, + struct ena_com_io_cq *io_cq) + { + size_t size; +- int prev_node = 0; + + memset(&io_cq->cdesc_addr, 0x0, sizeof(io_cq->cdesc_addr)); + +@@ -409,11 +401,8 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev, + + size = io_cq->cdesc_entry_size_in_bytes * io_cq->q_depth; + +- prev_node = dev_to_node(ena_dev->dmadev); +- set_dev_node(ena_dev->dmadev, ctx->numa_node); + io_cq->cdesc_addr.virt_addr = + dma_alloc_coherent(ena_dev->dmadev, size, &io_cq->cdesc_addr.phys_addr, GFP_KERNEL); +- set_dev_node(ena_dev->dmadev, prev_node); + if (!io_cq->cdesc_addr.virt_addr) { + io_cq->cdesc_addr.virt_addr = + dma_alloc_coherent(ena_dev->dmadev, size, &io_cq->cdesc_addr.phys_addr, +diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c +index d266a87297a5e..54798df8e2544 100644 +--- a/drivers/net/ethernet/cisco/enic/enic_main.c ++++ b/drivers/net/ethernet/cisco/enic/enic_main.c +@@ -1117,18 +1117,30 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, + pp->request = nla_get_u8(port[IFLA_PORT_REQUEST]); + + if (port[IFLA_PORT_PROFILE]) { ++ if (nla_len(port[IFLA_PORT_PROFILE]) != PORT_PROFILE_MAX) { ++ memcpy(pp, &prev_pp, sizeof(*pp)); ++ return -EINVAL; ++ } + pp->set |= ENIC_SET_NAME; + memcpy(pp->name, nla_data(port[IFLA_PORT_PROFILE]), + PORT_PROFILE_MAX); + } + + if (port[IFLA_PORT_INSTANCE_UUID]) { ++ if (nla_len(port[IFLA_PORT_INSTANCE_UUID]) != PORT_UUID_MAX) { ++ memcpy(pp, &prev_pp, sizeof(*pp)); ++ return -EINVAL; ++ } + pp->set |= ENIC_SET_INSTANCE; + memcpy(pp->instance_uuid, + nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX); + } + + if (port[IFLA_PORT_HOST_UUID]) { ++ if (nla_len(port[IFLA_PORT_HOST_UUID]) != PORT_UUID_MAX) { ++ memcpy(pp, &prev_pp, sizeof(*pp)); ++ return -EINVAL; ++ } + pp->set |= ENIC_SET_HOST; + memcpy(pp->host_uuid, + nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX); +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index a72d8a2eb0b31..881ece735dcf1 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -4130,6 +4130,14 @@ static int fec_enet_init(struct net_device *ndev) + return ret; + } + ++static void fec_enet_deinit(struct net_device *ndev) ++{ ++ struct fec_enet_private *fep = netdev_priv(ndev); ++ ++ netif_napi_del(&fep->napi); ++ fec_enet_free_queue(ndev); ++} ++ + #ifdef CONFIG_OF + static int fec_reset_phy(struct platform_device *pdev) + { +@@ -4524,6 +4532,7 @@ fec_probe(struct platform_device *pdev) + fec_enet_mii_remove(fep); + failed_mii_init: + failed_irq: ++ fec_enet_deinit(ndev); + failed_init: + fec_ptp_stop(pdev); + failed_reset: +@@ -4587,6 +4596,7 @@ fec_drv_remove(struct platform_device *pdev) + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(&pdev->dev); + ++ fec_enet_deinit(ndev); + free_netdev(ndev); + } + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index 181d9bfbee220..e32f6724f5681 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -104,14 +104,13 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) + struct timespec64 ts; + u64 ns; + +- if (fep->pps_enable == enable) +- return 0; +- +- fep->pps_channel = DEFAULT_PPS_CHANNEL; +- fep->reload_period = PPS_OUPUT_RELOAD_PERIOD; +- + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->pps_enable == enable) { ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ return 0; ++ } ++ + if (enable) { + /* clear capture or output compare interrupt status if have. + */ +@@ -532,6 +531,9 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + int ret = 0; + + if (rq->type == PTP_CLK_REQ_PPS) { ++ fep->pps_channel = DEFAULT_PPS_CHANNEL; ++ fep->reload_period = PPS_OUPUT_RELOAD_PERIOD; ++ + ret = fec_ptp_enable_pps(fep, on); + + return ret; +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index d9f6cc71d900a..e7d28432ba038 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -3135,6 +3135,16 @@ ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high) + case ICE_PHY_TYPE_HIGH_100G_AUI2: + speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB; + break; ++ case ICE_PHY_TYPE_HIGH_200G_CR4_PAM4: ++ case ICE_PHY_TYPE_HIGH_200G_SR4: ++ case ICE_PHY_TYPE_HIGH_200G_FR4: ++ case ICE_PHY_TYPE_HIGH_200G_LR4: ++ case ICE_PHY_TYPE_HIGH_200G_DR4: ++ case ICE_PHY_TYPE_HIGH_200G_KR4_PAM4: ++ case ICE_PHY_TYPE_HIGH_200G_AUI4_AOC_ACC: ++ case ICE_PHY_TYPE_HIGH_200G_AUI4: ++ speed_phy_type_high = ICE_AQ_LINK_SPEED_200GB; ++ break; + default: + speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; + break; +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 78b833b3e1d7e..62c8205fcebae 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3593,7 +3593,6 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch) + struct ice_pf *pf = vsi->back; + int new_rx = 0, new_tx = 0; + bool locked = false; +- u32 curr_combined; + int ret = 0; + + /* do not support changing channels in Safe Mode */ +@@ -3615,22 +3614,8 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch) + return -EOPNOTSUPP; + } + +- curr_combined = ice_get_combined_cnt(vsi); +- +- /* these checks are for cases where user didn't specify a particular +- * value on cmd line but we get non-zero value anyway via +- * get_channels(); look at ethtool.c in ethtool repository (the user +- * space part), particularly, do_schannels() routine +- */ +- if (ch->rx_count == vsi->num_rxq - curr_combined) +- ch->rx_count = 0; +- if (ch->tx_count == vsi->num_txq - curr_combined) +- ch->tx_count = 0; +- if (ch->combined_count == curr_combined) +- ch->combined_count = 0; +- +- if (!(ch->combined_count || (ch->rx_count && ch->tx_count))) { +- netdev_err(dev, "Please specify at least 1 Rx and 1 Tx channel\n"); ++ if (ch->rx_count && ch->tx_count) { ++ netdev_err(dev, "Dedicated RX or TX channels cannot be used simultaneously\n"); + return -EINVAL; + } + +diff --git a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c +index 2e9ad27cb9d13..6e8f2aab60801 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c +@@ -45,14 +45,15 @@ int ice_vsi_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) + return -EINVAL; + + err = ice_fltr_add_vlan(vsi, vlan); +- if (err && err != -EEXIST) { ++ if (!err) ++ vsi->num_vlan++; ++ else if (err == -EEXIST) ++ err = 0; ++ else + dev_err(ice_pf_to_dev(vsi->back), "Failure Adding VLAN %d on VSI %i, status %d\n", + vlan->vid, vsi->vsi_num, err); +- return err; +- } + +- vsi->num_vlan++; +- return 0; ++ return err; + } + + /** +diff --git a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c +index 6972d728431cb..1885ba618981d 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c +@@ -222,14 +222,19 @@ static int idpf_set_channels(struct net_device *netdev, + struct ethtool_channels *ch) + { + struct idpf_vport_config *vport_config; +- u16 combined, num_txq, num_rxq; + unsigned int num_req_tx_q; + unsigned int num_req_rx_q; + struct idpf_vport *vport; ++ u16 num_txq, num_rxq; + struct device *dev; + int err = 0; + u16 idx; + ++ if (ch->rx_count && ch->tx_count) { ++ netdev_err(netdev, "Dedicated RX or TX channels cannot be used simultaneously\n"); ++ return -EINVAL; ++ } ++ + idpf_vport_ctrl_lock(netdev); + vport = idpf_netdev_to_vport(netdev); + +@@ -239,20 +244,6 @@ static int idpf_set_channels(struct net_device *netdev, + num_txq = vport_config->user_config.num_req_tx_qs; + num_rxq = vport_config->user_config.num_req_rx_qs; + +- combined = min(num_txq, num_rxq); +- +- /* these checks are for cases where user didn't specify a particular +- * value on cmd line but we get non-zero value anyway via +- * get_channels(); look at ethtool.c in ethtool repository (the user +- * space part), particularly, do_schannels() routine +- */ +- if (ch->combined_count == combined) +- ch->combined_count = 0; +- if (ch->combined_count && ch->rx_count == num_rxq - combined) +- ch->rx_count = 0; +- if (ch->combined_count && ch->tx_count == num_txq - combined) +- ch->tx_count = 0; +- + num_req_tx_q = ch->combined_count + ch->tx_count; + num_req_rx_q = ch->combined_count + ch->rx_count; + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c +index 5d3532c27d57f..ae8a48c480708 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c +@@ -1394,6 +1394,7 @@ static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res) + } + + idpf_rx_init_buf_tail(vport); ++ idpf_vport_intr_ena(vport); + + err = idpf_send_config_queues_msg(vport); + if (err) { +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +index f5bc4a2780745..7fc77ed9d1232 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c +@@ -3747,9 +3747,9 @@ static void idpf_vport_intr_ena_irq_all(struct idpf_vport *vport) + */ + void idpf_vport_intr_deinit(struct idpf_vport *vport) + { ++ idpf_vport_intr_dis_irq_all(vport); + idpf_vport_intr_napi_dis_all(vport); + idpf_vport_intr_napi_del_all(vport); +- idpf_vport_intr_dis_irq_all(vport); + idpf_vport_intr_rel_irq(vport); + } + +@@ -4180,7 +4180,6 @@ int idpf_vport_intr_init(struct idpf_vport *vport) + + idpf_vport_intr_map_vector_to_qs(vport); + idpf_vport_intr_napi_add_all(vport); +- idpf_vport_intr_napi_ena_all(vport); + + err = vport->adapter->dev_ops.reg_ops.intr_reg_init(vport); + if (err) +@@ -4194,17 +4193,20 @@ int idpf_vport_intr_init(struct idpf_vport *vport) + if (err) + goto unroll_vectors_alloc; + +- idpf_vport_intr_ena_irq_all(vport); +- + return 0; + + unroll_vectors_alloc: +- idpf_vport_intr_napi_dis_all(vport); + idpf_vport_intr_napi_del_all(vport); + + return err; + } + ++void idpf_vport_intr_ena(struct idpf_vport *vport) ++{ ++ idpf_vport_intr_napi_ena_all(vport); ++ idpf_vport_intr_ena_irq_all(vport); ++} ++ + /** + * idpf_config_rss - Send virtchnl messages to configure RSS + * @vport: virtual port +diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +index df76493faa756..85a1466890d43 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h ++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h +@@ -988,6 +988,7 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport); + void idpf_vport_intr_update_itr_ena_irq(struct idpf_q_vector *q_vector); + void idpf_vport_intr_deinit(struct idpf_vport *vport); + int idpf_vport_intr_init(struct idpf_vport *vport); ++void idpf_vport_intr_ena(struct idpf_vport *vport); + enum pkt_hash_types idpf_ptype_to_htype(const struct idpf_rx_ptype_decoded *decoded); + int idpf_config_rss(struct idpf_vport *vport); + int idpf_init_rss(struct idpf_vport *vport); +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +index ed440dd0c4f9f..84fb6b8de2a12 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +@@ -3676,9 +3676,7 @@ struct ixgbe_info { + #define IXGBE_KRM_LINK_S1(P) ((P) ? 0x8200 : 0x4200) + #define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) + #define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C) +-#define IXGBE_KRM_AN_CNTL_4(P) ((P) ? 0x8238 : 0x4238) + #define IXGBE_KRM_AN_CNTL_8(P) ((P) ? 0x8248 : 0x4248) +-#define IXGBE_KRM_PCS_KX_AN(P) ((P) ? 0x9918 : 0x5918) + #define IXGBE_KRM_SGMII_CTRL(P) ((P) ? 0x82A0 : 0x42A0) + #define IXGBE_KRM_LP_BASE_PAGE_HIGH(P) ((P) ? 0x836C : 0x436C) + #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) +@@ -3688,7 +3686,6 @@ struct ixgbe_info { + #define IXGBE_KRM_PMD_FLX_MASK_ST20(P) ((P) ? 0x9054 : 0x5054) + #define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520) + #define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00) +-#define IXGBE_KRM_FLX_TMRS_CTRL_ST31(P) ((P) ? 0x9180 : 0x5180) + + #define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA ~(0x3 << 20) + #define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR BIT(20) +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +index 2decb0710b6e3..a5f6449344450 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +@@ -1722,59 +1722,9 @@ static int ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) + return -EINVAL; + } + +- (void)mac->ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- +- /* change mode enforcement rules to hybrid */ +- (void)mac->ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- reg_val |= 0x0400; +- +- (void)mac->ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- +- /* manually control the config */ +- (void)mac->ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- reg_val |= 0x20002240; +- +- (void)mac->ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- +- /* move the AN base page values */ +- (void)mac->ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- reg_val |= 0x1; +- +- (void)mac->ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- +- /* set the AN37 over CB mode */ +- (void)mac->ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- reg_val |= 0x20000000; +- +- (void)mac->ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- +- /* restart AN manually */ +- (void)mac->ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; +- +- (void)mac->ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); ++ status = mac->ops.write_iosf_sb_reg(hw, ++ IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + + /* Toggle port SW reset by AN reset. */ + status = ixgbe_restart_an_internal_phy_x550em(hw); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +index 1723e9912ae07..6cddb4da85b71 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +@@ -1407,7 +1407,10 @@ static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid, + otx2_qos_read_txschq_cfg(pfvf, node, old_cfg); + + /* delete the txschq nodes allocated for this node */ ++ otx2_qos_disable_sq(pfvf, qid); ++ otx2_qos_free_hw_node_schq(pfvf, node); + otx2_qos_free_sw_node_schq(pfvf, node); ++ pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; + + /* mark this node as htb inner node */ + WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER); +@@ -1554,6 +1557,7 @@ static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force + dwrr_del_node = true; + + /* destroy the leaf node */ ++ otx2_qos_disable_sq(pfvf, qid); + otx2_qos_destroy_node(pfvf, node); + pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h +index caa34b9c161e5..33e32584b07f5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h +@@ -102,8 +102,14 @@ static inline void + mlx5e_udp_gso_handle_tx_skb(struct sk_buff *skb) + { + int payload_len = skb_shinfo(skb)->gso_size + sizeof(struct udphdr); ++ struct udphdr *udphdr; + +- udp_hdr(skb)->len = htons(payload_len); ++ if (skb->encapsulation) ++ udphdr = (struct udphdr *)skb_inner_transport_header(skb); ++ else ++ udphdr = udp_hdr(skb); ++ ++ udphdr->len = htons(payload_len); + } + + struct mlx5e_accel_tx_state { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +index 41a2543a52cda..e51b03d4c717f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +@@ -750,8 +750,7 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, + err_fs_ft: + if (rx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); +- mlx5_del_flow_rules(rx->status.rule); +- mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); ++ mlx5_ipsec_rx_status_destroy(ipsec, rx); + err_add: + mlx5_destroy_flow_table(rx->ft.status); + err_fs_ft_status: +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h +index 82064614846f5..359050f0b54dd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h +@@ -97,18 +97,11 @@ mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features) + if (!x || !x->xso.offload_handle) + goto out_disable; + +- if (xo->inner_ipproto) { +- /* Cannot support tunnel packet over IPsec tunnel mode +- * because we cannot offload three IP header csum +- */ +- if (x->props.mode == XFRM_MODE_TUNNEL) +- goto out_disable; +- +- /* Only support UDP or TCP L4 checksum */ +- if (xo->inner_ipproto != IPPROTO_UDP && +- xo->inner_ipproto != IPPROTO_TCP) +- goto out_disable; +- } ++ /* Only support UDP or TCP L4 checksum */ ++ if (xo->inner_ipproto && ++ xo->inner_ipproto != IPPROTO_UDP && ++ xo->inner_ipproto != IPPROTO_TCP) ++ goto out_disable; + + return features; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 64497b6eebd36..47be07af214ff 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3790,7 +3790,7 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) + mlx5e_fold_sw_stats64(priv, stats); + } + +- stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer; ++ stats->rx_missed_errors = priv->stats.qcnt.rx_out_of_buffer; + + stats->rx_length_errors = + PPORT_802_3_GET(pstats, a_in_range_length_errors) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +index e21a3b4128ce8..0964b16ca5619 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +@@ -153,7 +153,11 @@ mlx5e_tx_get_gso_ihs(struct mlx5e_txqsq *sq, struct sk_buff *skb, int *hopbyhop) + + *hopbyhop = 0; + if (skb->encapsulation) { +- ihs = skb_inner_tcp_all_headers(skb); ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ++ ihs = skb_inner_transport_offset(skb) + ++ sizeof(struct udphdr); ++ else ++ ihs = skb_inner_tcp_all_headers(skb); + stats->tso_inner_packets++; + stats->tso_inner_bytes += skb->len - ihs; + } else { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index 37598d116f3b8..58a452d20daf7 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -720,6 +720,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) + struct mlx5_core_dev *dev; + u8 mode; + #endif ++ bool roce_support; + int i; + + for (i = 0; i < ldev->ports; i++) +@@ -746,6 +747,11 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) + if (mlx5_sriov_is_enabled(ldev->pf[i].dev)) + return false; + #endif ++ roce_support = mlx5_get_roce_state(ldev->pf[MLX5_LAG_P1].dev); ++ for (i = 1; i < ldev->ports; i++) ++ if (mlx5_get_roce_state(ldev->pf[i].dev) != roce_support) ++ return false; ++ + return true; + } + +@@ -913,8 +919,10 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) + } else if (roce_lag) { + dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; + mlx5_rescan_drivers_locked(dev0); +- for (i = 1; i < ldev->ports; i++) +- mlx5_nic_vport_enable_roce(ldev->pf[i].dev); ++ for (i = 1; i < ldev->ports; i++) { ++ if (mlx5_get_roce_state(ldev->pf[i].dev)) ++ mlx5_nic_vport_enable_roce(ldev->pf[i].dev); ++ } + } else if (shared_fdb) { + int i; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c +index dd5d186dc6148..f6deb5a3f8202 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c +@@ -100,10 +100,6 @@ static bool ft_create_alias_supported(struct mlx5_core_dev *dev) + + static bool mlx5_sd_is_supported(struct mlx5_core_dev *dev, u8 host_buses) + { +- /* Feature is currently implemented for PFs only */ +- if (!mlx5_core_is_pf(dev)) +- return false; +- + /* Honor the SW implementation limit */ + if (host_buses > MLX5_SD_MAX_GROUP_SZ) + return false; +@@ -162,6 +158,14 @@ static int sd_init(struct mlx5_core_dev *dev) + bool sdm; + int err; + ++ /* Feature is currently implemented for PFs only */ ++ if (!mlx5_core_is_pf(dev)) ++ return 0; ++ ++ /* Block on embedded CPU PFs */ ++ if (mlx5_core_is_ecpf(dev)) ++ return 0; ++ + if (!MLX5_CAP_MCAM_REG(dev, mpir)) + return 0; + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +index af50ff9e5f267..ce49c9514f911 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +@@ -539,7 +539,7 @@ mlxsw_sp_span_gretap6_route(const struct net_device *to_dev, + if (!dst || dst->error) + goto out; + +- rt6 = container_of(dst, struct rt6_info, dst); ++ rt6 = dst_rt6_info(dst); + + dev = dst->dev; + *saddrp = fl6.saddr; +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +index 61d88207eed42..6695ed661ef83 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +@@ -474,14 +474,14 @@ static int lan966x_port_hwtstamp_set(struct net_device *dev, + cfg->source != HWTSTAMP_SOURCE_PHYLIB) + return -EOPNOTSUPP; + ++ if (cfg->source == HWTSTAMP_SOURCE_NETDEV && !port->lan966x->ptp) ++ return -EOPNOTSUPP; ++ + err = lan966x_ptp_setup_traps(port, cfg); + if (err) + return err; + + if (cfg->source == HWTSTAMP_SOURCE_NETDEV) { +- if (!port->lan966x->ptp) +- return -EOPNOTSUPP; +- + err = lan966x_ptp_hwtstamp_set(port, cfg, extack); + if (err) { + lan966x_ptp_del_traps(port); +diff --git a/drivers/net/ethernet/ti/icssg/icssg_classifier.c b/drivers/net/ethernet/ti/icssg/icssg_classifier.c +index 6df53ab17fbc5..902a2717785cb 100644 +--- a/drivers/net/ethernet/ti/icssg/icssg_classifier.c ++++ b/drivers/net/ethernet/ti/icssg/icssg_classifier.c +@@ -360,7 +360,7 @@ void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr) + { + const u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, }; + +- rx_class_ft1_set_start_len(miig_rt, slice, 0, 6); ++ rx_class_ft1_set_start_len(miig_rt, slice, ETH_ALEN, ETH_ALEN); + rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr); + rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr); + rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ); +diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c +index 2d5b021b4ea60..fef4eff7753a7 100644 +--- a/drivers/net/ipvlan/ipvlan_core.c ++++ b/drivers/net/ipvlan/ipvlan_core.c +@@ -439,7 +439,7 @@ static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb) + + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + +- err = ip_local_out(net, skb->sk, skb); ++ err = ip_local_out(net, NULL, skb); + if (unlikely(net_xmit_eval(err))) + DEV_STATS_INC(dev, tx_errors); + else +@@ -494,7 +494,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) + + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + +- err = ip6_local_out(dev_net(dev), skb->sk, skb); ++ err = ip6_local_out(dev_net(dev), NULL, skb); + if (unlikely(net_xmit_eval(err))) + DEV_STATS_INC(dev, tx_errors); + else +diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c +index a4d2e76a8d587..16789cd446e9e 100644 +--- a/drivers/net/netkit.c ++++ b/drivers/net/netkit.c +@@ -55,6 +55,7 @@ static void netkit_prep_forward(struct sk_buff *skb, bool xnet) + skb_scrub_packet(skb, xnet); + skb->priority = 0; + nf_skip_egress(skb, true); ++ skb_reset_mac_header(skb); + } + + static struct netkit *netkit_priv(const struct net_device *dev) +@@ -78,6 +79,7 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev) + skb_orphan_frags(skb, GFP_ATOMIC))) + goto drop; + netkit_prep_forward(skb, !net_eq(dev_net(dev), dev_net(peer))); ++ eth_skb_pkt_type(skb, peer); + skb->dev = peer; + entry = rcu_dereference(nk->active); + if (entry) +@@ -85,7 +87,7 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev) + switch (ret) { + case NETKIT_NEXT: + case NETKIT_PASS: +- skb->protocol = eth_type_trans(skb, skb->dev); ++ eth_skb_pull_mac(skb); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) { + dev_sw_netstats_tx_add(dev, 1, len); +@@ -155,6 +157,16 @@ static void netkit_set_multicast(struct net_device *dev) + /* Nothing to do, we receive whatever gets pushed to us! */ + } + ++static int netkit_set_macaddr(struct net_device *dev, void *sa) ++{ ++ struct netkit *nk = netkit_priv(dev); ++ ++ if (nk->mode != NETKIT_L2) ++ return -EOPNOTSUPP; ++ ++ return eth_mac_addr(dev, sa); ++} ++ + static void netkit_set_headroom(struct net_device *dev, int headroom) + { + struct netkit *nk = netkit_priv(dev), *nk2; +@@ -198,6 +210,7 @@ static const struct net_device_ops netkit_netdev_ops = { + .ndo_start_xmit = netkit_xmit, + .ndo_set_rx_mode = netkit_set_multicast, + .ndo_set_rx_headroom = netkit_set_headroom, ++ .ndo_set_mac_address = netkit_set_macaddr, + .ndo_get_iflink = netkit_get_iflink, + .ndo_get_peer_dev = netkit_peer_dev, + .ndo_get_stats64 = netkit_get_stats, +@@ -300,9 +313,11 @@ static int netkit_validate(struct nlattr *tb[], struct nlattr *data[], + + if (!attr) + return 0; +- NL_SET_ERR_MSG_ATTR(extack, attr, +- "Setting Ethernet address is not supported"); +- return -EOPNOTSUPP; ++ if (nla_len(attr) != ETH_ALEN) ++ return -EINVAL; ++ if (!is_valid_ether_addr(nla_data(attr))) ++ return -EADDRNOTAVAIL; ++ return 0; + } + + static struct rtnl_link_ops netkit_link_ops; +@@ -365,6 +380,9 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev, + strscpy(ifname, "nk%d", IFNAMSIZ); + ifname_assign_type = NET_NAME_ENUM; + } ++ if (mode != NETKIT_L2 && ++ (tb[IFLA_ADDRESS] || tbp[IFLA_ADDRESS])) ++ return -EOPNOTSUPP; + + net = rtnl_link_get_net(src_net, tbp); + if (IS_ERR(net)) +@@ -379,7 +397,7 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev, + + netif_inherit_tso_max(peer, dev); + +- if (mode == NETKIT_L2) ++ if (mode == NETKIT_L2 && !(ifmp && tbp[IFLA_ADDRESS])) + eth_hw_addr_random(peer); + if (ifmp && dev->ifindex) + peer->ifindex = ifmp->ifi_index; +@@ -402,7 +420,7 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev, + if (err < 0) + goto err_configure_peer; + +- if (mode == NETKIT_L2) ++ if (mode == NETKIT_L2 && !tb[IFLA_ADDRESS]) + eth_hw_addr_random(dev); + if (tb[IFLA_IFNAME]) + nla_strscpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ); +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index 87780465cd0d5..13370439a7cae 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -3516,7 +3516,7 @@ static int lan8841_config_intr(struct phy_device *phydev) + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + err = phy_read(phydev, LAN8814_INTS); +- if (err) ++ if (err < 0) + return err; + + /* Enable / disable interrupts. It is OK to enable PTP interrupt +@@ -3532,6 +3532,14 @@ static int lan8841_config_intr(struct phy_device *phydev) + return err; + + err = phy_read(phydev, LAN8814_INTS); ++ if (err < 0) ++ return err; ++ ++ /* Getting a positive value doesn't mean that is an error, it ++ * just indicates what was the status. Therefore make sure to ++ * clear the value and say that there is no error. ++ */ ++ err = 0; + } + + return err; +@@ -4814,6 +4822,7 @@ static struct phy_driver ksphy_driver[] = { + /* PHY_BASIC_FEATURES */ + .probe = kszphy_probe, + .config_init = ksz8061_config_init, ++ .soft_reset = genphy_soft_reset, + .config_intr = kszphy_config_intr, + .handle_interrupt = kszphy_handle_interrupt, + .suspend = kszphy_suspend, +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index cbea246664795..8e82184be5e7d 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -879,7 +879,7 @@ static int smsc95xx_start_rx_path(struct usbnet *dev) + static int smsc95xx_reset(struct usbnet *dev) + { + struct smsc95xx_priv *pdata = dev->driver_priv; +- u32 read_buf, write_buf, burst_cap; ++ u32 read_buf, burst_cap; + int ret = 0, timeout; + + netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n"); +@@ -1003,10 +1003,13 @@ static int smsc95xx_reset(struct usbnet *dev) + return ret; + netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf); + ++ ret = smsc95xx_read_reg(dev, LED_GPIO_CFG, &read_buf); ++ if (ret < 0) ++ return ret; + /* Configure GPIO pins as LED outputs */ +- write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | +- LED_GPIO_CFG_FDX_LED; +- ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf); ++ read_buf |= LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | ++ LED_GPIO_CFG_FDX_LED; ++ ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, read_buf); + if (ret < 0) + return ret; + +diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c +index bb95ce43cd97d..c3af9ad5e1547 100644 +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -653,7 +653,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk, + skb->dev = dev; + + rcu_read_lock(); +- nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr); ++ nexthop = rt6_nexthop(dst_rt6_info(dst), &ipv6_hdr(skb)->daddr); + neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); + if (unlikely(!neigh)) + neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); +@@ -860,7 +860,7 @@ static int vrf_rt6_create(struct net_device *dev) + static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) + { + struct dst_entry *dst = skb_dst(skb); +- struct rtable *rt = (struct rtable *)dst; ++ struct rtable *rt = dst_rtable(dst); + struct net_device *dev = dst->dev; + unsigned int hh_len = LL_RESERVED_SPACE(dev); + struct neighbour *neigh; +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index 3a9148fb1422b..6b64f28a9174d 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -2528,7 +2528,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + } + + if (!info) { +- u32 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; ++ u32 rt6i_flags = dst_rt6_info(ndst)->rt6i_flags; + + err = encap_bypass_if_local(skb, dev, vxlan, AF_INET6, + dst_port, ifindex, vni, +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 095f59e7aa937..d513fd27589df 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -414,7 +414,15 @@ static inline void nvme_end_req_zoned(struct request *req) + } + } + +-static inline void nvme_end_req(struct request *req) ++static inline void __nvme_end_req(struct request *req) ++{ ++ nvme_end_req_zoned(req); ++ nvme_trace_bio_complete(req); ++ if (req->cmd_flags & REQ_NVME_MPATH) ++ nvme_mpath_end_request(req); ++} ++ ++void nvme_end_req(struct request *req) + { + blk_status_t status = nvme_error_status(nvme_req(req)->status); + +@@ -424,10 +432,7 @@ static inline void nvme_end_req(struct request *req) + else + nvme_log_error(req); + } +- nvme_end_req_zoned(req); +- nvme_trace_bio_complete(req); +- if (req->cmd_flags & REQ_NVME_MPATH) +- nvme_mpath_end_request(req); ++ __nvme_end_req(req); + blk_mq_end_request(req, status); + } + +@@ -476,7 +481,7 @@ void nvme_complete_batch_req(struct request *req) + { + trace_nvme_complete_rq(req); + nvme_cleanup_cmd(req); +- nvme_end_req_zoned(req); ++ __nvme_end_req(req); + } + EXPORT_SYMBOL_GPL(nvme_complete_batch_req); + +diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c +index d16e976ae1a47..a4e46eb20be63 100644 +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -118,7 +118,8 @@ void nvme_failover_req(struct request *req) + blk_steal_bios(&ns->head->requeue_list, req); + spin_unlock_irqrestore(&ns->head->requeue_lock, flags); + +- blk_mq_end_request(req, 0); ++ nvme_req(req)->status = 0; ++ nvme_end_req(req); + kblockd_schedule_work(&ns->head->requeue_work); + } + +diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h +index 05532c2811774..d7bcc6d51e84e 100644 +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -767,6 +767,7 @@ static inline bool nvme_state_terminal(struct nvme_ctrl *ctrl) + } + } + ++void nvme_end_req(struct request *req); + void nvme_complete_rq(struct request *req); + void nvme_complete_batch_req(struct request *req); + +diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c +index 7fda69395c1ef..dfdff6aba6953 100644 +--- a/drivers/nvme/target/configfs.c ++++ b/drivers/nvme/target/configfs.c +@@ -676,10 +676,18 @@ static ssize_t nvmet_ns_enable_store(struct config_item *item, + if (kstrtobool(page, &enable)) + return -EINVAL; + ++ /* ++ * take a global nvmet_config_sem because the disable routine has a ++ * window where it releases the subsys-lock, giving a chance to ++ * a parallel enable to concurrently execute causing the disable to ++ * have a misaccounting of the ns percpu_ref. ++ */ ++ down_write(&nvmet_config_sem); + if (enable) + ret = nvmet_ns_enable(ns); + else + nvmet_ns_disable(ns); ++ up_write(&nvmet_config_sem); + + return ret ? ret : count; + } +diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c +index 746a11dcb67f1..c43a1479de2ce 100644 +--- a/drivers/pci/controller/dwc/pcie-designware-ep.c ++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c +@@ -604,11 +604,16 @@ static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap) + int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep) + { + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); ++ struct dw_pcie_ep_func *ep_func; ++ struct device *dev = pci->dev; ++ struct pci_epc *epc = ep->epc; + unsigned int offset, ptm_cap_base; + unsigned int nbars; + u8 hdr_type; ++ u8 func_no; ++ int i, ret; ++ void *addr; + u32 reg; +- int i; + + hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) & + PCI_HEADER_TYPE_MASK; +@@ -619,6 +624,58 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep) + return -EIO; + } + ++ dw_pcie_version_detect(pci); ++ ++ dw_pcie_iatu_detect(pci); ++ ++ ret = dw_pcie_edma_detect(pci); ++ if (ret) ++ return ret; ++ ++ if (!ep->ib_window_map) { ++ ep->ib_window_map = devm_bitmap_zalloc(dev, pci->num_ib_windows, ++ GFP_KERNEL); ++ if (!ep->ib_window_map) ++ goto err_remove_edma; ++ } ++ ++ if (!ep->ob_window_map) { ++ ep->ob_window_map = devm_bitmap_zalloc(dev, pci->num_ob_windows, ++ GFP_KERNEL); ++ if (!ep->ob_window_map) ++ goto err_remove_edma; ++ } ++ ++ if (!ep->outbound_addr) { ++ addr = devm_kcalloc(dev, pci->num_ob_windows, sizeof(phys_addr_t), ++ GFP_KERNEL); ++ if (!addr) ++ goto err_remove_edma; ++ ep->outbound_addr = addr; ++ } ++ ++ for (func_no = 0; func_no < epc->max_functions; func_no++) { ++ ++ ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); ++ if (ep_func) ++ continue; ++ ++ ep_func = devm_kzalloc(dev, sizeof(*ep_func), GFP_KERNEL); ++ if (!ep_func) ++ goto err_remove_edma; ++ ++ ep_func->func_no = func_no; ++ ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no, ++ PCI_CAP_ID_MSI); ++ ep_func->msix_cap = dw_pcie_ep_find_capability(ep, func_no, ++ PCI_CAP_ID_MSIX); ++ ++ list_add_tail(&ep_func->list, &ep->func_list); ++ } ++ ++ if (ep->ops->init) ++ ep->ops->init(ep); ++ + offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); + ptm_cap_base = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM); + +@@ -658,14 +715,17 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep) + dw_pcie_dbi_ro_wr_dis(pci); + + return 0; ++ ++err_remove_edma: ++ dw_pcie_edma_remove(pci); ++ ++ return ret; + } + EXPORT_SYMBOL_GPL(dw_pcie_ep_init_complete); + + int dw_pcie_ep_init(struct dw_pcie_ep *ep) + { + int ret; +- void *addr; +- u8 func_no; + struct resource *res; + struct pci_epc *epc; + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +@@ -673,7 +733,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) + struct platform_device *pdev = to_platform_device(dev); + struct device_node *np = dev->of_node; + const struct pci_epc_features *epc_features; +- struct dw_pcie_ep_func *ep_func; + + INIT_LIST_HEAD(&ep->func_list); + +@@ -691,26 +750,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) + if (ep->ops->pre_init) + ep->ops->pre_init(ep); + +- dw_pcie_version_detect(pci); +- +- dw_pcie_iatu_detect(pci); +- +- ep->ib_window_map = devm_bitmap_zalloc(dev, pci->num_ib_windows, +- GFP_KERNEL); +- if (!ep->ib_window_map) +- return -ENOMEM; +- +- ep->ob_window_map = devm_bitmap_zalloc(dev, pci->num_ob_windows, +- GFP_KERNEL); +- if (!ep->ob_window_map) +- return -ENOMEM; +- +- addr = devm_kcalloc(dev, pci->num_ob_windows, sizeof(phys_addr_t), +- GFP_KERNEL); +- if (!addr) +- return -ENOMEM; +- ep->outbound_addr = addr; +- + epc = devm_pci_epc_create(dev, &epc_ops); + if (IS_ERR(epc)) { + dev_err(dev, "Failed to create epc device\n"); +@@ -724,23 +763,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) + if (ret < 0) + epc->max_functions = 1; + +- for (func_no = 0; func_no < epc->max_functions; func_no++) { +- ep_func = devm_kzalloc(dev, sizeof(*ep_func), GFP_KERNEL); +- if (!ep_func) +- return -ENOMEM; +- +- ep_func->func_no = func_no; +- ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no, +- PCI_CAP_ID_MSI); +- ep_func->msix_cap = dw_pcie_ep_find_capability(ep, func_no, +- PCI_CAP_ID_MSIX); +- +- list_add_tail(&ep_func->list, &ep->func_list); +- } +- +- if (ep->ops->init) +- ep->ops->init(ep); +- + ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size, + ep->page_size); + if (ret < 0) { +@@ -756,25 +778,25 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) + goto err_exit_epc_mem; + } + +- ret = dw_pcie_edma_detect(pci); +- if (ret) +- goto err_free_epc_mem; +- + if (ep->ops->get_features) { + epc_features = ep->ops->get_features(ep); + if (epc_features->core_init_notifier) + return 0; + } + ++ /* ++ * NOTE:- Avoid accessing the hardware (Ex:- DBI space) before this ++ * step as platforms that implement 'core_init_notifier' feature may ++ * not have the hardware ready (i.e. core initialized) for access ++ * (Ex: tegra194). Any hardware access on such platforms result ++ * in system hang. ++ */ + ret = dw_pcie_ep_init_complete(ep); + if (ret) +- goto err_remove_edma; ++ goto err_free_epc_mem; + + return 0; + +-err_remove_edma: +- dw_pcie_edma_remove(pci); +- + err_free_epc_mem: + pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem, + epc->mem->window.page_size); +diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c +index 1f7b662cb8e15..e440c09d1dc11 100644 +--- a/drivers/pci/controller/dwc/pcie-tegra194.c ++++ b/drivers/pci/controller/dwc/pcie-tegra194.c +@@ -2273,11 +2273,14 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) + ret = tegra_pcie_config_ep(pcie, pdev); + if (ret < 0) + goto fail; ++ else ++ return 0; + break; + + default: + dev_err(dev, "Invalid PCIe device type %d\n", + pcie->of_data->mode); ++ ret = -EINVAL; + } + + fail: +diff --git a/drivers/pci/of_property.c b/drivers/pci/of_property.c +index c2c7334152bc0..03539e5053720 100644 +--- a/drivers/pci/of_property.c ++++ b/drivers/pci/of_property.c +@@ -238,6 +238,8 @@ static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs, + return 0; + + int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL); ++ if (!int_map) ++ return -ENOMEM; + mapp = int_map; + + list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index e5f243dd42884..70b8c87055cb6 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -4629,7 +4629,7 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) + * avoid LTSSM race as recommended in Implementation Note at the + * end of PCIe r6.0.1 sec 7.5.3.7. + */ +- rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt); ++ rc = pcie_wait_for_link_status(pdev, true, false); + if (rc) + return rc; + +diff --git a/drivers/pci/pcie/edr.c b/drivers/pci/pcie/edr.c +index 5f4914d313a17..e86298dbbcff6 100644 +--- a/drivers/pci/pcie/edr.c ++++ b/drivers/pci/pcie/edr.c +@@ -32,10 +32,10 @@ static int acpi_enable_dpc(struct pci_dev *pdev) + int status = 0; + + /* +- * Behavior when calling unsupported _DSM functions is undefined, +- * so check whether EDR_PORT_DPC_ENABLE_DSM is supported. ++ * Per PCI Firmware r3.3, sec 4.6.12, EDR_PORT_DPC_ENABLE_DSM is ++ * optional. Return success if it's not implemented. + */ +- if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 5, ++ if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 6, + 1ULL << EDR_PORT_DPC_ENABLE_DSM)) + return 0; + +@@ -46,12 +46,7 @@ static int acpi_enable_dpc(struct pci_dev *pdev) + argv4.package.count = 1; + argv4.package.elements = &req; + +- /* +- * Per Downstream Port Containment Related Enhancements ECN to PCI +- * Firmware Specification r3.2, sec 4.6.12, EDR_PORT_DPC_ENABLE_DSM is +- * optional. Return success if it's not implemented. +- */ +- obj = acpi_evaluate_dsm(adev->handle, &pci_acpi_dsm_guid, 5, ++ obj = acpi_evaluate_dsm(adev->handle, &pci_acpi_dsm_guid, 6, + EDR_PORT_DPC_ENABLE_DSM, &argv4); + if (!obj) + return 0; +@@ -85,8 +80,9 @@ static struct pci_dev *acpi_dpc_port_get(struct pci_dev *pdev) + u16 port; + + /* +- * Behavior when calling unsupported _DSM functions is undefined, +- * so check whether EDR_PORT_DPC_ENABLE_DSM is supported. ++ * If EDR_PORT_LOCATE_DSM is not implemented under the target of ++ * EDR, the target is the port that experienced the containment ++ * event (PCI Firmware r3.3, sec 4.6.13). + */ + if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 5, + 1ULL << EDR_PORT_LOCATE_DSM)) +@@ -103,6 +99,16 @@ static struct pci_dev *acpi_dpc_port_get(struct pci_dev *pdev) + return NULL; + } + ++ /* ++ * Bit 31 represents the success/failure of the operation. If bit ++ * 31 is set, the operation failed. ++ */ ++ if (obj->integer.value & BIT(31)) { ++ ACPI_FREE(obj); ++ pci_err(pdev, "Locate Port _DSM failed\n"); ++ return NULL; ++ } ++ + /* + * Firmware returns DPC port BDF details in following format: + * 15:8 = bus +diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c +index 8a81be2dd5ecf..88c17c1d6d499 100644 +--- a/drivers/perf/arm_dmc620_pmu.c ++++ b/drivers/perf/arm_dmc620_pmu.c +@@ -542,12 +542,16 @@ static int dmc620_pmu_event_init(struct perf_event *event) + if (event->cpu < 0) + return -EINVAL; + ++ hwc->idx = -1; ++ ++ if (event->group_leader == event) ++ return 0; ++ + /* + * We can't atomically disable all HW counters so only one event allowed, + * although software events are acceptable. + */ +- if (event->group_leader != event && +- !is_software_event(event->group_leader)) ++ if (!is_software_event(event->group_leader)) + return -EINVAL; + + for_each_sibling_event(sibling, event->group_leader) { +@@ -556,7 +560,6 @@ static int dmc620_pmu_event_init(struct perf_event *event) + return -EINVAL; + } + +- hwc->idx = -1; + return 0; + } + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +index c21cdb8dbfe74..acc2b5b9ea255 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +@@ -1382,6 +1382,13 @@ static const u8 qmp_dp_v5_voltage_swing_hbr_rbr[4][4] = { + { 0x3f, 0xff, 0xff, 0xff } + }; + ++static const u8 qmp_dp_v6_voltage_swing_hbr_rbr[4][4] = { ++ { 0x27, 0x2f, 0x36, 0x3f }, ++ { 0x31, 0x3e, 0x3f, 0xff }, ++ { 0x36, 0x3f, 0xff, 0xff }, ++ { 0x3f, 0xff, 0xff, 0xff } ++}; ++ + static const u8 qmp_dp_v6_pre_emphasis_hbr_rbr[4][4] = { + { 0x20, 0x2d, 0x34, 0x3a }, + { 0x20, 0x2e, 0x35, 0xff }, +@@ -2001,6 +2008,51 @@ static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = { + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + }; + ++static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = { ++ .offsets = &qmp_combo_offsets_v3, ++ ++ .serdes_tbl = sm8550_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8550_usb3_serdes_tbl), ++ .tx_tbl = sm8550_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8550_usb3_tx_tbl), ++ .rx_tbl = sm8550_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8550_usb3_rx_tbl), ++ .pcs_tbl = sm8550_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_tbl), ++ .pcs_usb_tbl = sm8550_usb3_pcs_usb_tbl, ++ .pcs_usb_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_usb_tbl), ++ ++ .dp_serdes_tbl = qmp_v6_dp_serdes_tbl, ++ .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl), ++ .dp_tx_tbl = qmp_v6_dp_tx_tbl, ++ .dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v6_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v6_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v6_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v6_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3), ++ ++ .swing_hbr_rbr = &qmp_dp_v6_voltage_swing_hbr_rbr, ++ .pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr, ++ .swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2, ++ .pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2, ++ ++ .dp_aux_init = qmp_v4_dp_aux_init, ++ .configure_dp_tx = qmp_v4_configure_dp_tx, ++ .configure_dp_phy = qmp_v4_configure_dp_phy, ++ .calibrate_dp_phy = qmp_v4_calibrate_dp_phy, ++ ++ .regs = qmp_v6_usb3phy_regs_layout, ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++}; ++ + static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp) + { + const struct qmp_phy_cfg *cfg = qmp->cfg; +@@ -3631,7 +3683,7 @@ static const struct of_device_id qmp_combo_of_match_table[] = { + }, + { + .compatible = "qcom,sm8650-qmp-usb3-dp-phy", +- .data = &sm8550_usb3dpphy_cfg, ++ .data = &sm8650_usb3dpphy_cfg, + }, + { + .compatible = "qcom,x1e80100-qmp-usb3-dp-phy", +diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c +index c25357ca1963e..b9f067de8ef0e 100644 +--- a/drivers/pinctrl/qcom/pinctrl-sm7150.c ++++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c +@@ -65,7 +65,7 @@ enum { + .intr_detection_width = 2, \ + } + +-#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ ++#define SDC_QDSD_PINGROUP(pg_name, _tile, ctl, pull, drv) \ + { \ + .grp = PINCTRL_PINGROUP(#pg_name, \ + pg_name##_pins, \ +@@ -75,7 +75,7 @@ enum { + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ +- .tile = SOUTH, \ ++ .tile = _tile, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ +@@ -101,7 +101,7 @@ enum { + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ +- .tile = SOUTH, \ ++ .tile = WEST, \ + .mux_bit = -1, \ + .pull_bit = 3, \ + .drv_bit = 0, \ +@@ -1199,13 +1199,13 @@ static const struct msm_pingroup sm7150_groups[] = { + [117] = PINGROUP(117, NORTH, _, _, _, _, _, _, _, _, _), + [118] = PINGROUP(118, NORTH, _, _, _, _, _, _, _, _, _), + [119] = UFS_RESET(ufs_reset, 0x9f000), +- [120] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x9a000, 15, 0), +- [121] = SDC_QDSD_PINGROUP(sdc1_clk, 0x9a000, 13, 6), +- [122] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x9a000, 11, 3), +- [123] = SDC_QDSD_PINGROUP(sdc1_data, 0x9a000, 9, 0), +- [124] = SDC_QDSD_PINGROUP(sdc2_clk, 0x98000, 14, 6), +- [125] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x98000, 11, 3), +- [126] = SDC_QDSD_PINGROUP(sdc2_data, 0x98000, 9, 0), ++ [120] = SDC_QDSD_PINGROUP(sdc1_rclk, WEST, 0x9a000, 15, 0), ++ [121] = SDC_QDSD_PINGROUP(sdc1_clk, WEST, 0x9a000, 13, 6), ++ [122] = SDC_QDSD_PINGROUP(sdc1_cmd, WEST, 0x9a000, 11, 3), ++ [123] = SDC_QDSD_PINGROUP(sdc1_data, WEST, 0x9a000, 9, 0), ++ [124] = SDC_QDSD_PINGROUP(sdc2_clk, SOUTH, 0x98000, 14, 6), ++ [125] = SDC_QDSD_PINGROUP(sdc2_cmd, SOUTH, 0x98000, 11, 3), ++ [126] = SDC_QDSD_PINGROUP(sdc2_data, SOUTH, 0x98000, 9, 0), + }; + + static const struct msm_gpio_wakeirq_map sm7150_pdc_map[] = { +diff --git a/drivers/pinctrl/renesas/pfc-r8a779h0.c b/drivers/pinctrl/renesas/pfc-r8a779h0.c +index afa8f06c85cf5..0cbfe7637fc97 100644 +--- a/drivers/pinctrl/renesas/pfc-r8a779h0.c ++++ b/drivers/pinctrl/renesas/pfc-r8a779h0.c +@@ -75,10 +75,10 @@ + #define GPSR0_9 F_(MSIOF5_SYNC, IP1SR0_7_4) + #define GPSR0_8 F_(MSIOF5_SS1, IP1SR0_3_0) + #define GPSR0_7 F_(MSIOF5_SS2, IP0SR0_31_28) +-#define GPSR0_6 F_(IRQ0, IP0SR0_27_24) +-#define GPSR0_5 F_(IRQ1, IP0SR0_23_20) +-#define GPSR0_4 F_(IRQ2, IP0SR0_19_16) +-#define GPSR0_3 F_(IRQ3, IP0SR0_15_12) ++#define GPSR0_6 F_(IRQ0_A, IP0SR0_27_24) ++#define GPSR0_5 F_(IRQ1_A, IP0SR0_23_20) ++#define GPSR0_4 F_(IRQ2_A, IP0SR0_19_16) ++#define GPSR0_3 F_(IRQ3_A, IP0SR0_15_12) + #define GPSR0_2 F_(GP0_02, IP0SR0_11_8) + #define GPSR0_1 F_(GP0_01, IP0SR0_7_4) + #define GPSR0_0 F_(GP0_00, IP0SR0_3_0) +@@ -265,10 +265,10 @@ + #define IP0SR0_3_0 F_(0, 0) FM(ERROROUTC_N_B) FM(TCLK2_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + #define IP0SR0_7_4 F_(0, 0) FM(MSIOF3_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + #define IP0SR0_11_8 F_(0, 0) FM(MSIOF3_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +-#define IP0SR0_15_12 FM(IRQ3) FM(MSIOF3_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +-#define IP0SR0_19_16 FM(IRQ2) FM(MSIOF3_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +-#define IP0SR0_23_20 FM(IRQ1) FM(MSIOF3_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) +-#define IP0SR0_27_24 FM(IRQ0) FM(MSIOF3_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0SR0_15_12 FM(IRQ3_A) FM(MSIOF3_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0SR0_19_16 FM(IRQ2_A) FM(MSIOF3_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0SR0_23_20 FM(IRQ1_A) FM(MSIOF3_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0SR0_27_24 FM(IRQ0_A) FM(MSIOF3_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + #define IP0SR0_31_28 FM(MSIOF5_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) + + /* IP1SR0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 4 5 6 7 8 9 A B C D E F */ +@@ -672,16 +672,16 @@ static const u16 pinmux_data[] = { + + PINMUX_IPSR_GPSR(IP0SR0_11_8, MSIOF3_SS2), + +- PINMUX_IPSR_GPSR(IP0SR0_15_12, IRQ3), ++ PINMUX_IPSR_GPSR(IP0SR0_15_12, IRQ3_A), + PINMUX_IPSR_GPSR(IP0SR0_15_12, MSIOF3_SCK), + +- PINMUX_IPSR_GPSR(IP0SR0_19_16, IRQ2), ++ PINMUX_IPSR_GPSR(IP0SR0_19_16, IRQ2_A), + PINMUX_IPSR_GPSR(IP0SR0_19_16, MSIOF3_TXD), + +- PINMUX_IPSR_GPSR(IP0SR0_23_20, IRQ1), ++ PINMUX_IPSR_GPSR(IP0SR0_23_20, IRQ1_A), + PINMUX_IPSR_GPSR(IP0SR0_23_20, MSIOF3_RXD), + +- PINMUX_IPSR_GPSR(IP0SR0_27_24, IRQ0), ++ PINMUX_IPSR_GPSR(IP0SR0_27_24, IRQ0_A), + PINMUX_IPSR_GPSR(IP0SR0_27_24, MSIOF3_SYNC), + + PINMUX_IPSR_GPSR(IP0SR0_31_28, MSIOF5_SS2), +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index 20425afc6b331..248ab71b9f9da 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -892,6 +892,8 @@ static int rzg2l_set_power_source(struct rzg2l_pinctrl *pctrl, u32 pin, u32 caps + val = PVDD_1800; + break; + case 2500: ++ if (!(caps & (PIN_CFG_IO_VMC_ETH0 | PIN_CFG_IO_VMC_ETH1))) ++ return -EINVAL; + val = PVDD_2500; + break; + case 3300: +diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c +index 910df7c654f48..003e765dedea1 100644 +--- a/drivers/platform/x86/intel/tpmi.c ++++ b/drivers/platform/x86/intel/tpmi.c +@@ -763,8 +763,11 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev) + * when actual device nodes created outside this + * loop via tpmi_create_devices(). + */ +- if (pfs->pfs_header.tpmi_id == TPMI_INFO_ID) +- tpmi_process_info(tpmi_info, pfs); ++ if (pfs->pfs_header.tpmi_id == TPMI_INFO_ID) { ++ ret = tpmi_process_info(tpmi_info, pfs); ++ if (ret) ++ return ret; ++ } + + if (pfs->pfs_header.tpmi_id == TPMI_CONTROL_ID) + tpmi_set_control_base(auxdev, tpmi_info, pfs); +diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c +index ef730200a04bd..bb8e72deb3542 100644 +--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c ++++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c +@@ -240,6 +240,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_ + bool read_blocked = 0, write_blocked = 0; + struct intel_tpmi_plat_info *plat_info; + struct tpmi_uncore_struct *tpmi_uncore; ++ bool uncore_sysfs_added = false; + int ret, i, pkg = 0; + int num_resources; + +@@ -384,9 +385,15 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_ + } + /* Point to next cluster offset */ + cluster_offset >>= UNCORE_MAX_CLUSTER_PER_DOMAIN; ++ uncore_sysfs_added = true; + } + } + ++ if (!uncore_sysfs_added) { ++ ret = -ENODEV; ++ goto remove_clusters; ++ } ++ + auxiliary_set_drvdata(auxdev, tpmi_uncore); + + tpmi_uncore->root_cluster.root_domain = true; +diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c +index 82429e59999da..87a4a381bd988 100644 +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -3044,10 +3044,9 @@ static void tpacpi_send_radiosw_update(void) + + static void hotkey_exit(void) + { +-#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL + mutex_lock(&hotkey_mutex); ++#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL + hotkey_poll_stop_sync(); +- mutex_unlock(&hotkey_mutex); + #endif + dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY, + "restoring original HKEY status and mask\n"); +@@ -3057,6 +3056,8 @@ static void hotkey_exit(void) + hotkey_mask_set(hotkey_orig_mask)) | + hotkey_status_set(false)) != 0) + pr_err("failed to restore hot key mask to BIOS defaults\n"); ++ ++ mutex_unlock(&hotkey_mutex); + } + + static void __init hotkey_unmap(const unsigned int scancode) +diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c +index 08d4ee369287e..dd871ffe979c3 100644 +--- a/drivers/regulator/bd71828-regulator.c ++++ b/drivers/regulator/bd71828-regulator.c +@@ -206,14 +206,11 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + .suspend_reg = BD71828_REG_BUCK1_SUSP_VOLT, + .suspend_mask = BD71828_MASK_BUCK1267_VOLT, + .suspend_on_mask = BD71828_MASK_SUSP_EN, +- .lpsr_on_mask = BD71828_MASK_LPSR_EN, + /* + * LPSR voltage is same as SUSPEND voltage. Allow +- * setting it so that regulator can be set enabled at +- * LPSR state ++ * only enabling/disabling regulator for LPSR state + */ +- .lpsr_reg = BD71828_REG_BUCK1_SUSP_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, ++ .lpsr_on_mask = BD71828_MASK_LPSR_EN, + }, + .reg_inits = buck1_inits, + .reg_init_amnt = ARRAY_SIZE(buck1_inits), +@@ -288,13 +285,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK3_VOLT, +- .idle_reg = BD71828_REG_BUCK3_VOLT, +- .suspend_reg = BD71828_REG_BUCK3_VOLT, +- .lpsr_reg = BD71828_REG_BUCK3_VOLT, + .run_mask = BD71828_MASK_BUCK3_VOLT, +- .idle_mask = BD71828_MASK_BUCK3_VOLT, +- .suspend_mask = BD71828_MASK_BUCK3_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK3_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -329,13 +320,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK4_VOLT, +- .idle_reg = BD71828_REG_BUCK4_VOLT, +- .suspend_reg = BD71828_REG_BUCK4_VOLT, +- .lpsr_reg = BD71828_REG_BUCK4_VOLT, + .run_mask = BD71828_MASK_BUCK4_VOLT, +- .idle_mask = BD71828_MASK_BUCK4_VOLT, +- .suspend_mask = BD71828_MASK_BUCK4_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK4_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -370,13 +355,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_BUCK5_VOLT, +- .idle_reg = BD71828_REG_BUCK5_VOLT, +- .suspend_reg = BD71828_REG_BUCK5_VOLT, +- .lpsr_reg = BD71828_REG_BUCK5_VOLT, + .run_mask = BD71828_MASK_BUCK5_VOLT, +- .idle_mask = BD71828_MASK_BUCK5_VOLT, +- .suspend_mask = BD71828_MASK_BUCK5_VOLT, +- .lpsr_mask = BD71828_MASK_BUCK5_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -493,13 +472,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO1_VOLT, +- .idle_reg = BD71828_REG_LDO1_VOLT, +- .suspend_reg = BD71828_REG_LDO1_VOLT, +- .lpsr_reg = BD71828_REG_LDO1_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -533,13 +506,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO2_VOLT, +- .idle_reg = BD71828_REG_LDO2_VOLT, +- .suspend_reg = BD71828_REG_LDO2_VOLT, +- .lpsr_reg = BD71828_REG_LDO2_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -573,13 +540,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO3_VOLT, +- .idle_reg = BD71828_REG_LDO3_VOLT, +- .suspend_reg = BD71828_REG_LDO3_VOLT, +- .lpsr_reg = BD71828_REG_LDO3_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -614,13 +575,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO4_VOLT, +- .idle_reg = BD71828_REG_LDO4_VOLT, +- .suspend_reg = BD71828_REG_LDO4_VOLT, +- .lpsr_reg = BD71828_REG_LDO4_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -655,13 +610,7 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + ROHM_DVS_LEVEL_SUSPEND | + ROHM_DVS_LEVEL_LPSR, + .run_reg = BD71828_REG_LDO5_VOLT, +- .idle_reg = BD71828_REG_LDO5_VOLT, +- .suspend_reg = BD71828_REG_LDO5_VOLT, +- .lpsr_reg = BD71828_REG_LDO5_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +@@ -720,9 +669,6 @@ static const struct bd71828_regulator_data bd71828_rdata[] = { + .suspend_reg = BD71828_REG_LDO7_VOLT, + .lpsr_reg = BD71828_REG_LDO7_VOLT, + .run_mask = BD71828_MASK_LDO_VOLT, +- .idle_mask = BD71828_MASK_LDO_VOLT, +- .suspend_mask = BD71828_MASK_LDO_VOLT, +- .lpsr_mask = BD71828_MASK_LDO_VOLT, + .idle_on_mask = BD71828_MASK_IDLE_EN, + .suspend_on_mask = BD71828_MASK_SUSP_EN, + .lpsr_on_mask = BD71828_MASK_LPSR_EN, +diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c +index d492683365532..6e1ace660b8cf 100644 +--- a/drivers/regulator/helpers.c ++++ b/drivers/regulator/helpers.c +@@ -161,6 +161,32 @@ int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev) + } + EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap); + ++static int write_separate_vsel_and_range(struct regulator_dev *rdev, ++ unsigned int sel, unsigned int range) ++{ ++ bool range_updated; ++ int ret; ++ ++ ret = regmap_update_bits_base(rdev->regmap, rdev->desc->vsel_range_reg, ++ rdev->desc->vsel_range_mask, ++ range, &range_updated, false, false); ++ if (ret) ++ return ret; ++ ++ /* ++ * Some PMICs treat the vsel_reg same as apply-bit. Force it to be ++ * written if the range changed, even if the old selector was same as ++ * the new one ++ */ ++ if (rdev->desc->range_applied_by_vsel && range_updated) ++ return regmap_write_bits(rdev->regmap, ++ rdev->desc->vsel_reg, ++ rdev->desc->vsel_mask, sel); ++ ++ return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, ++ rdev->desc->vsel_mask, sel); ++} ++ + /** + * regulator_set_voltage_sel_pickable_regmap - pickable range set_voltage_sel + * +@@ -199,21 +225,12 @@ int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev, + range = rdev->desc->linear_range_selectors_bitfield[i]; + range <<= ffs(rdev->desc->vsel_range_mask) - 1; + +- if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) { +- ret = regmap_update_bits(rdev->regmap, +- rdev->desc->vsel_reg, ++ if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) ++ ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + rdev->desc->vsel_range_mask | + rdev->desc->vsel_mask, sel | range); +- } else { +- ret = regmap_update_bits(rdev->regmap, +- rdev->desc->vsel_range_reg, +- rdev->desc->vsel_range_mask, range); +- if (ret) +- return ret; +- +- ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, +- rdev->desc->vsel_mask, sel); +- } ++ else ++ ret = write_separate_vsel_and_range(rdev, sel, range); + + if (ret) + return ret; +diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c +index 9b7c3d77789e3..3c9d79e003e4b 100644 +--- a/drivers/regulator/tps6287x-regulator.c ++++ b/drivers/regulator/tps6287x-regulator.c +@@ -115,6 +115,7 @@ static struct regulator_desc tps6287x_reg = { + .vsel_mask = 0xFF, + .vsel_range_reg = TPS6287X_CTRL2, + .vsel_range_mask = TPS6287X_CTRL2_VRANGE, ++ .range_applied_by_vsel = true, + .ramp_reg = TPS6287X_CTRL1, + .ramp_mask = TPS6287X_CTRL1_VRAMP, + .ramp_delay_table = tps6287x_ramp_table, +diff --git a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c +index b7f0c87797577..5fad61785e72f 100644 +--- a/drivers/regulator/tps6594-regulator.c ++++ b/drivers/regulator/tps6594-regulator.c +@@ -287,30 +287,30 @@ static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = { + static const struct regulator_desc multi_regs[] = { + TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_VOUT_1(1), ++ TPS6594_REG_BUCKX_VOUT_1(0), + TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_CTRL(1), ++ TPS6594_REG_BUCKX_CTRL(0), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 4000, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK34", "buck34", TPS6594_BUCK_3, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_VOUT_1(3), ++ TPS6594_REG_BUCKX_VOUT_1(2), + TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_CTRL(3), ++ TPS6594_REG_BUCKX_CTRL(2), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 0, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK123", "buck123", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_VOUT_1(1), ++ TPS6594_REG_BUCKX_VOUT_1(0), + TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_CTRL(1), ++ TPS6594_REG_BUCKX_CTRL(0), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 4000, 0, NULL, 0, 0), + TPS6594_REGULATOR("BUCK1234", "buck1234", TPS6594_BUCK_1, + REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_VOUT_1(1), ++ TPS6594_REG_BUCKX_VOUT_1(0), + TPS6594_MASK_BUCKS_VSET, +- TPS6594_REG_BUCKX_CTRL(1), ++ TPS6594_REG_BUCKX_CTRL(0), + TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, + 4, 4000, 0, NULL, 0, 0), + }; +diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c +index cce0bafd4c926..f13837907bd5e 100644 +--- a/drivers/s390/crypto/ap_bus.c ++++ b/drivers/s390/crypto/ap_bus.c +@@ -767,9 +767,9 @@ static void ap_check_bindings_complete(void) + if (bound == apqns) { + if (!completion_done(&ap_apqn_bindings_complete)) { + complete_all(&ap_apqn_bindings_complete); ++ ap_send_bindings_complete_uevent(); + pr_debug("%s all apqn bindings complete\n", __func__); + } +- ap_send_bindings_complete_uevent(); + } + } + } +@@ -929,6 +929,12 @@ static int ap_device_probe(struct device *dev) + goto out; + } + ++ /* ++ * Rearm the bindings complete completion to trigger ++ * bindings complete when all devices are bound again ++ */ ++ reinit_completion(&ap_apqn_bindings_complete); ++ + /* Add queue/card to list of active queues/cards */ + spin_lock_bh(&ap_queues_lock); + if (is_queue_dev(dev)) +diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h +index 613eab7297046..41fe8a043d61f 100644 +--- a/drivers/s390/net/qeth_core.h ++++ b/drivers/s390/net/qeth_core.h +@@ -956,7 +956,7 @@ static inline struct dst_entry *qeth_dst_check_rcu(struct sk_buff *skb, + struct dst_entry *dst = skb_dst(skb); + struct rt6_info *rt; + +- rt = (struct rt6_info *) dst; ++ rt = dst_rt6_info(dst); + if (dst) { + if (proto == htons(ETH_P_IPV6)) + dst = dst_check(dst, rt6_get_cookie(rt)); +@@ -970,15 +970,14 @@ static inline struct dst_entry *qeth_dst_check_rcu(struct sk_buff *skb, + static inline __be32 qeth_next_hop_v4_rcu(struct sk_buff *skb, + struct dst_entry *dst) + { +- struct rtable *rt = (struct rtable *) dst; +- +- return (rt) ? rt_nexthop(rt, ip_hdr(skb)->daddr) : ip_hdr(skb)->daddr; ++ return (dst) ? rt_nexthop(dst_rtable(dst), ip_hdr(skb)->daddr) : ++ ip_hdr(skb)->daddr; + } + + static inline struct in6_addr *qeth_next_hop_v6_rcu(struct sk_buff *skb, + struct dst_entry *dst) + { +- struct rt6_info *rt = (struct rt6_info *) dst; ++ struct rt6_info *rt = dst_rt6_info(dst); + + if (rt && !ipv6_addr_any(&rt->rt6i_gateway)) + return &rt->rt6i_gateway; +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 65cdc8b77e358..caac482fff2ff 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -3707,8 +3707,10 @@ static int sd_revalidate_disk(struct gendisk *disk) + */ + if (sdkp->first_scan || + q->limits.max_sectors > q->limits.max_dev_sectors || +- q->limits.max_sectors > q->limits.max_hw_sectors) ++ q->limits.max_sectors > q->limits.max_hw_sectors) { + q->limits.max_sectors = rw_max; ++ q->limits.max_user_sectors = rw_max; ++ } + + sdkp->first_scan = 0; + +diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c +index 0efc1c3bee5f5..3e7cf04aaf2a6 100644 +--- a/drivers/soundwire/cadence_master.c ++++ b/drivers/soundwire/cadence_master.c +@@ -1880,7 +1880,7 @@ struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns, + + /* check if we found a PDI, else find in bi-directional */ + if (!pdi) +- pdi = cdns_find_pdi(cdns, 2, stream->num_bd, stream->bd, ++ pdi = cdns_find_pdi(cdns, 0, stream->num_bd, stream->bd, + dai_id); + + if (pdi) { +diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c +index 4a68abcdcc353..4c4ff074e3f6f 100644 +--- a/drivers/spi/spi-stm32.c ++++ b/drivers/spi/spi-stm32.c +@@ -1016,8 +1016,10 @@ static irqreturn_t stm32fx_spi_irq_event(int irq, void *dev_id) + static irqreturn_t stm32fx_spi_irq_thread(int irq, void *dev_id) + { + struct spi_controller *ctrl = dev_id; ++ struct stm32_spi *spi = spi_controller_get_devdata(ctrl); + + spi_finalize_current_transfer(ctrl); ++ stm32fx_spi_disable(spi); + + return IRQ_HANDLED; + } +@@ -1055,7 +1057,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) + mask |= STM32H7_SPI_SR_TXP | STM32H7_SPI_SR_RXP; + + if (!(sr & mask)) { +- dev_warn(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", ++ dev_vdbg(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", + sr, ier); + spin_unlock_irqrestore(&spi->lock, flags); + return IRQ_NONE; +@@ -1185,8 +1187,6 @@ static int stm32_spi_prepare_msg(struct spi_controller *ctrl, + ~clrb) | setb, + spi->base + spi->cfg->regs->cpol.reg); + +- stm32_spi_enable(spi); +- + spin_unlock_irqrestore(&spi->lock, flags); + + return 0; +@@ -1204,6 +1204,7 @@ static void stm32fx_spi_dma_tx_cb(void *data) + + if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { + spi_finalize_current_transfer(spi->ctrl); ++ stm32fx_spi_disable(spi); + } + } + +@@ -1218,6 +1219,7 @@ static void stm32_spi_dma_rx_cb(void *data) + struct stm32_spi *spi = data; + + spi_finalize_current_transfer(spi->ctrl); ++ spi->cfg->disable(spi); + } + + /** +@@ -1305,6 +1307,8 @@ static int stm32fx_spi_transfer_one_irq(struct stm32_spi *spi) + + stm32_spi_set_bits(spi, STM32FX_SPI_CR2, cr2); + ++ stm32_spi_enable(spi); ++ + /* starting data transfer when buffer is loaded */ + if (spi->tx_buf) + spi->cfg->write_tx(spi); +@@ -1341,6 +1345,8 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) + + spin_lock_irqsave(&spi->lock, flags); + ++ stm32_spi_enable(spi); ++ + /* Be sure to have data in fifo before starting data transfer */ + if (spi->tx_buf) + stm32h7_spi_write_txfifo(spi); +@@ -1372,6 +1378,8 @@ static void stm32fx_spi_transfer_one_dma_start(struct stm32_spi *spi) + */ + stm32_spi_set_bits(spi, STM32FX_SPI_CR2, STM32FX_SPI_CR2_ERRIE); + } ++ ++ stm32_spi_enable(spi); + } + + /** +@@ -1405,6 +1413,8 @@ static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) + + stm32_spi_set_bits(spi, STM32H7_SPI_IER, ier); + ++ stm32_spi_enable(spi); ++ + if (STM32_SPI_HOST_MODE(spi)) + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); + } +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index a2c467d9e92f5..2cea7aeb10f95 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -1242,6 +1242,7 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) + else + rx_dev = ctlr->dev.parent; + ++ ret = -ENOMSG; + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + /* The sync is done before each transfer. */ + unsigned long attrs = DMA_ATTR_SKIP_CPU_SYNC; +@@ -1271,6 +1272,9 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) + } + } + } ++ /* No transfer has been mapped, bail out with success */ ++ if (ret) ++ return 0; + + ctlr->cur_rx_dma_dev = rx_dev; + ctlr->cur_tx_dma_dev = tx_dev; +diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c +index 9ed1180fe31f1..937c15324513f 100644 +--- a/drivers/spmi/spmi-pmic-arb.c ++++ b/drivers/spmi/spmi-pmic-arb.c +@@ -1462,8 +1462,8 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) + */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); + core = devm_ioremap(&ctrl->dev, res->start, resource_size(res)); +- if (IS_ERR(core)) +- return PTR_ERR(core); ++ if (!core) ++ return -ENOMEM; + + pmic_arb->core_size = resource_size(res); + +@@ -1495,15 +1495,15 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev) + "obsrvr"); + pmic_arb->rd_base = devm_ioremap(&ctrl->dev, res->start, + resource_size(res)); +- if (IS_ERR(pmic_arb->rd_base)) +- return PTR_ERR(pmic_arb->rd_base); ++ if (!pmic_arb->rd_base) ++ return -ENOMEM; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "chnls"); + pmic_arb->wr_base = devm_ioremap(&ctrl->dev, res->start, + resource_size(res)); +- if (IS_ERR(pmic_arb->wr_base)) +- return PTR_ERR(pmic_arb->wr_base); ++ if (!pmic_arb->wr_base) ++ return -ENOMEM; + } + + pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS; +diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c +index 8541995008da8..aa6f266b62a14 100644 +--- a/drivers/staging/greybus/arche-apb-ctrl.c ++++ b/drivers/staging/greybus/arche-apb-ctrl.c +@@ -466,6 +466,7 @@ static const struct of_device_id arche_apb_ctrl_of_match[] = { + { .compatible = "usbffff,2", }, + { }, + }; ++MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match); + + static struct platform_driver arche_apb_ctrl_device_driver = { + .probe = arche_apb_ctrl_probe, +diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c +index 891b75327d7f7..b33977ccd5271 100644 +--- a/drivers/staging/greybus/arche-platform.c ++++ b/drivers/staging/greybus/arche-platform.c +@@ -619,14 +619,7 @@ static const struct of_device_id arche_platform_of_match[] = { + { .compatible = "google,arche-platform", }, + { }, + }; +- +-static const struct of_device_id arche_combined_id[] = { +- /* Use PID/VID of SVC device */ +- { .compatible = "google,arche-platform", }, +- { .compatible = "usbffff,2", }, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, arche_combined_id); ++MODULE_DEVICE_TABLE(of, arche_platform_of_match); + + static struct platform_driver arche_platform_device_driver = { + .probe = arche_platform_probe, +diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c +index a5c2fe963866d..00360f4a04854 100644 +--- a/drivers/staging/greybus/light.c ++++ b/drivers/staging/greybus/light.c +@@ -142,6 +142,9 @@ static int __gb_lights_flash_brightness_set(struct gb_channel *channel) + channel = get_channel_from_mode(channel->light, + GB_CHANNEL_MODE_TORCH); + ++ if (!channel) ++ return -EINVAL; ++ + /* For not flash we need to convert brightness to intensity */ + intensity = channel->intensity_uA.min + + (channel->intensity_uA.step * channel->led->brightness); +@@ -528,7 +531,10 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) + } + + channel_flash = get_channel_from_mode(light, GB_CHANNEL_MODE_FLASH); +- WARN_ON(!channel_flash); ++ if (!channel_flash) { ++ dev_err(dev, "failed to get flash channel from mode\n"); ++ return -EINVAL; ++ } + + fled = &channel_flash->fled; + +diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c +index 5efb2b593be33..3d2b83d6ab51a 100644 +--- a/drivers/tty/serial/max3100.c ++++ b/drivers/tty/serial/max3100.c +@@ -45,6 +45,9 @@ + #include <linux/freezer.h> + #include <linux/tty.h> + #include <linux/tty_flip.h> ++#include <linux/types.h> ++ ++#include <asm/unaligned.h> + + #include <linux/serial_max3100.h> + +@@ -191,7 +194,7 @@ static void max3100_timeout(struct timer_list *t) + static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx) + { + struct spi_message message; +- u16 etx, erx; ++ __be16 etx, erx; + int status; + struct spi_transfer tran = { + .tx_buf = &etx, +@@ -213,7 +216,7 @@ static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx) + return 0; + } + +-static int max3100_handlerx(struct max3100_port *s, u16 rx) ++static int max3100_handlerx_unlocked(struct max3100_port *s, u16 rx) + { + unsigned int status = 0; + int ret = 0, cts; +@@ -254,6 +257,17 @@ static int max3100_handlerx(struct max3100_port *s, u16 rx) + return ret; + } + ++static int max3100_handlerx(struct max3100_port *s, u16 rx) ++{ ++ unsigned long flags; ++ int ret; ++ ++ uart_port_lock_irqsave(&s->port, &flags); ++ ret = max3100_handlerx_unlocked(s, rx); ++ uart_port_unlock_irqrestore(&s->port, flags); ++ return ret; ++} ++ + static void max3100_work(struct work_struct *w) + { + struct max3100_port *s = container_of(w, struct max3100_port, work); +@@ -738,13 +752,14 @@ static int max3100_probe(struct spi_device *spi) + mutex_lock(&max3100s_lock); + + if (!uart_driver_registered) { +- uart_driver_registered = 1; + retval = uart_register_driver(&max3100_uart_driver); + if (retval) { + printk(KERN_ERR "Couldn't register max3100 uart driver\n"); + mutex_unlock(&max3100s_lock); + return retval; + } ++ ++ uart_driver_registered = 1; + } + + for (i = 0; i < MAX_MAX3100; i++) +@@ -830,6 +845,7 @@ static void max3100_remove(struct spi_device *spi) + } + pr_debug("removing max3100 driver\n"); + uart_unregister_driver(&max3100_uart_driver); ++ uart_driver_registered = 0; + + mutex_unlock(&max3100s_lock); + } +diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c +index 12915fffac279..ace2c4b333acc 100644 +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -18,6 +18,7 @@ + #include <linux/module.h> + #include <linux/property.h> + #include <linux/regmap.h> ++#include <linux/sched.h> + #include <linux/serial_core.h> + #include <linux/serial.h> + #include <linux/tty.h> +@@ -25,7 +26,6 @@ + #include <linux/spi/spi.h> + #include <linux/uaccess.h> + #include <linux/units.h> +-#include <uapi/linux/sched/types.h> + + #define SC16IS7XX_NAME "sc16is7xx" + #define SC16IS7XX_MAX_DEVS 8 +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index e512eaa57ed56..a6f3517dce749 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -1271,9 +1271,14 @@ static void sci_dma_rx_chan_invalidate(struct sci_port *s) + static void sci_dma_rx_release(struct sci_port *s) + { + struct dma_chan *chan = s->chan_rx_saved; ++ struct uart_port *port = &s->port; ++ unsigned long flags; + ++ uart_port_lock_irqsave(port, &flags); + s->chan_rx_saved = NULL; + sci_dma_rx_chan_invalidate(s); ++ uart_port_unlock_irqrestore(port, flags); ++ + dmaengine_terminate_sync(chan); + dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0], + sg_dma_address(&s->sg_rx[0])); +diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c +index 958fc40eae86b..0655afe7f9779 100644 +--- a/drivers/usb/fotg210/fotg210-core.c ++++ b/drivers/usb/fotg210/fotg210-core.c +@@ -95,6 +95,7 @@ static int fotg210_gemini_init(struct fotg210 *fotg, struct resource *res, + + /** + * fotg210_vbus() - Called by gadget driver to enable/disable VBUS ++ * @fotg: pointer to a private fotg210 object + * @enable: true to enable VBUS, false to disable VBUS + */ + void fotg210_vbus(struct fotg210 *fotg, bool enable) +diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c +index 4a42574b4a7fe..ec1dceb087293 100644 +--- a/drivers/usb/gadget/function/u_audio.c ++++ b/drivers/usb/gadget/function/u_audio.c +@@ -57,13 +57,13 @@ struct uac_rtd_params { + + /* Volume/Mute controls and their state */ + int fu_id; /* Feature Unit ID */ +- struct snd_kcontrol *snd_kctl_volume; +- struct snd_kcontrol *snd_kctl_mute; ++ struct snd_ctl_elem_id snd_kctl_volume_id; ++ struct snd_ctl_elem_id snd_kctl_mute_id; + s16 volume_min, volume_max, volume_res; + s16 volume; + int mute; + +- struct snd_kcontrol *snd_kctl_rate; /* read-only current rate */ ++ struct snd_ctl_elem_id snd_kctl_rate_id; /* read-only current rate */ + int srate; /* selected samplerate */ + int active; /* playback/capture running */ + +@@ -494,14 +494,13 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep) + static void set_active(struct uac_rtd_params *prm, bool active) + { + // notifying through the Rate ctrl +- struct snd_kcontrol *kctl = prm->snd_kctl_rate; + unsigned long flags; + + spin_lock_irqsave(&prm->lock, flags); + if (prm->active != active) { + prm->active = active; + snd_ctl_notify(prm->uac->card, SNDRV_CTL_EVENT_MASK_VALUE, +- &kctl->id); ++ &prm->snd_kctl_rate_id); + } + spin_unlock_irqrestore(&prm->lock, flags); + } +@@ -807,7 +806,7 @@ int u_audio_set_volume(struct g_audio *audio_dev, int playback, s16 val) + + if (change) + snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE, +- &prm->snd_kctl_volume->id); ++ &prm->snd_kctl_volume_id); + + return 0; + } +@@ -856,7 +855,7 @@ int u_audio_set_mute(struct g_audio *audio_dev, int playback, int val) + + if (change) + snd_ctl_notify(uac->card, SNDRV_CTL_EVENT_MASK_VALUE, +- &prm->snd_kctl_mute->id); ++ &prm->snd_kctl_mute_id); + + return 0; + } +@@ -1331,7 +1330,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, + err = snd_ctl_add(card, kctl); + if (err < 0) + goto snd_fail; +- prm->snd_kctl_mute = kctl; ++ prm->snd_kctl_mute_id = kctl->id; + prm->mute = 0; + } + +@@ -1359,7 +1358,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, + err = snd_ctl_add(card, kctl); + if (err < 0) + goto snd_fail; +- prm->snd_kctl_volume = kctl; ++ prm->snd_kctl_volume_id = kctl->id; + prm->volume = fu->volume_max; + prm->volume_max = fu->volume_max; + prm->volume_min = fu->volume_min; +@@ -1383,7 +1382,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, + err = snd_ctl_add(card, kctl); + if (err < 0) + goto snd_fail; +- prm->snd_kctl_rate = kctl; ++ prm->snd_kctl_rate_id = kctl->id; + } + + strscpy(card->driver, card_name, sizeof(card->driver)); +@@ -1420,6 +1419,8 @@ void g_audio_cleanup(struct g_audio *g_audio) + return; + + uac = g_audio->uac; ++ g_audio->uac = NULL; ++ + card = uac->card; + if (card) + snd_card_free_when_closed(card); +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 69dd866698833..990008aebe8fd 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -2269,24 +2269,24 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) + } + + static struct xhci_interrupter * +-xhci_alloc_interrupter(struct xhci_hcd *xhci, int segs, gfp_t flags) ++xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags) + { + struct device *dev = xhci_to_hcd(xhci)->self.sysdev; + struct xhci_interrupter *ir; +- unsigned int num_segs = segs; ++ unsigned int max_segs; + int ret; + ++ if (!segs) ++ segs = ERST_DEFAULT_SEGS; ++ ++ max_segs = BIT(HCS_ERST_MAX(xhci->hcs_params2)); ++ segs = min(segs, max_segs); ++ + ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev)); + if (!ir) + return NULL; + +- /* number of ring segments should be greater than 0 */ +- if (segs <= 0) +- num_segs = min_t(unsigned int, 1 << HCS_ERST_MAX(xhci->hcs_params2), +- ERST_MAX_SEGS); +- +- ir->event_ring = xhci_ring_alloc(xhci, num_segs, 1, TYPE_EVENT, 0, +- flags); ++ ir->event_ring = xhci_ring_alloc(xhci, segs, 1, TYPE_EVENT, 0, flags); + if (!ir->event_ring) { + xhci_warn(xhci, "Failed to allocate interrupter event ring\n"); + kfree(ir); +@@ -2344,7 +2344,7 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir, + } + + struct xhci_interrupter * +-xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg) ++xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs) + { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_interrupter *ir; +@@ -2354,7 +2354,7 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg) + if (!xhci->interrupters || xhci->max_interrupters <= 1) + return NULL; + +- ir = xhci_alloc_interrupter(xhci, num_seg, GFP_KERNEL); ++ ir = xhci_alloc_interrupter(xhci, segs, GFP_KERNEL); + if (!ir) + return NULL; + +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 6f4bf98a62824..31566e82bbd39 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1392,8 +1392,8 @@ struct urb_priv { + struct xhci_td td[] __counted_by(num_tds); + }; + +-/* Reasonable limit for number of Event Ring segments (spec allows 32k) */ +-#define ERST_MAX_SEGS 2 ++/* Number of Event Ring segments to allocate, when amount is not specified. (spec allows 32k) */ ++#define ERST_DEFAULT_SEGS 2 + /* Poll every 60 seconds */ + #define POLL_TIMEOUT 60 + /* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */ +@@ -1833,7 +1833,7 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, + void xhci_free_container_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx); + struct xhci_interrupter * +-xhci_create_secondary_interrupter(struct usb_hcd *hcd, int num_seg); ++xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs); + void xhci_remove_secondary_interrupter(struct usb_hcd + *hcd, struct xhci_interrupter *ir); + +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index bd6ae92aa39e7..7801501837b69 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -619,7 +619,8 @@ static int ucsi_read_pdos(struct ucsi_connector *con, + u64 command; + int ret; + +- if (ucsi->quirks & UCSI_NO_PARTNER_PDOS) ++ if (is_partner && ++ ucsi->quirks & UCSI_NO_PARTNER_PDOS) + return 0; + + command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num); +@@ -823,12 +824,6 @@ static int ucsi_register_partner_pdos(struct ucsi_connector *con) + return PTR_ERR(cap); + + con->partner_source_caps = cap; +- +- ret = typec_partner_set_usb_power_delivery(con->partner, con->partner_pd); +- if (ret) { +- usb_power_delivery_unregister_capabilities(con->partner_source_caps); +- return ret; +- } + } + + ret = ucsi_get_pdos(con, TYPEC_SINK, 1, caps.pdo); +@@ -843,15 +838,9 @@ static int ucsi_register_partner_pdos(struct ucsi_connector *con) + return PTR_ERR(cap); + + con->partner_sink_caps = cap; +- +- ret = typec_partner_set_usb_power_delivery(con->partner, con->partner_pd); +- if (ret) { +- usb_power_delivery_unregister_capabilities(con->partner_sink_caps); +- return ret; +- } + } + +- return 0; ++ return typec_partner_set_usb_power_delivery(con->partner, con->partner_pd); + } + + static void ucsi_unregister_partner_pdos(struct ucsi_connector *con) +@@ -1572,7 +1561,6 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) + } + + con->port_source_caps = pd_cap; +- typec_port_set_usb_power_delivery(con->port, con->pd); + } + + memset(&pd_caps, 0, sizeof(pd_caps)); +@@ -1589,9 +1577,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) + } + + con->port_sink_caps = pd_cap; +- typec_port_set_usb_power_delivery(con->port, con->pd); + } + ++ typec_port_set_usb_power_delivery(con->port, con->pd); ++ + /* Alternate modes */ + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON); + if (ret) { +diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c +index fb5392b749fff..e80c5d75b5419 100644 +--- a/drivers/vfio/pci/vfio_pci_intrs.c ++++ b/drivers/vfio/pci/vfio_pci_intrs.c +@@ -277,8 +277,10 @@ static int vfio_intx_enable(struct vfio_pci_core_device *vdev, + return -ENOMEM; + + ctx = vfio_irq_ctx_alloc(vdev, 0); +- if (!ctx) ++ if (!ctx) { ++ kfree(name); + return -ENOMEM; ++ } + + ctx->name = name; + ctx->trigger = trigger; +diff --git a/drivers/video/backlight/mp3309c.c b/drivers/video/backlight/mp3309c.c +index c80a1481e742b..4e98e60417d23 100644 +--- a/drivers/video/backlight/mp3309c.c ++++ b/drivers/video/backlight/mp3309c.c +@@ -205,8 +205,9 @@ static int mp3309c_parse_fwnode(struct mp3309c_chip *chip, + struct mp3309c_platform_data *pdata) + { + int ret, i; +- unsigned int num_levels, tmp_value; ++ unsigned int tmp_value; + struct device *dev = chip->dev; ++ int num_levels; + + if (!dev_fwnode(dev)) + return dev_err_probe(dev, -ENODEV, "failed to get firmware node\n"); +diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c +index 1f5b3dd31fcfc..89bc8da80519f 100644 +--- a/drivers/virtio/virtio_balloon.c ++++ b/drivers/virtio/virtio_balloon.c +@@ -450,7 +450,7 @@ static void start_update_balloon_size(struct virtio_balloon *vb) + vb->adjustment_signal_pending = true; + if (!vb->adjustment_in_progress) { + vb->adjustment_in_progress = true; +- pm_stay_awake(vb->vdev->dev.parent); ++ pm_stay_awake(&vb->vdev->dev); + } + spin_unlock_irqrestore(&vb->adjustment_lock, flags); + +@@ -462,7 +462,7 @@ static void end_update_balloon_size(struct virtio_balloon *vb) + spin_lock_irq(&vb->adjustment_lock); + if (!vb->adjustment_signal_pending && vb->adjustment_in_progress) { + vb->adjustment_in_progress = false; +- pm_relax(vb->vdev->dev.parent); ++ pm_relax(&vb->vdev->dev); + } + spin_unlock_irq(&vb->adjustment_lock); + } +@@ -1029,6 +1029,15 @@ static int virtballoon_probe(struct virtio_device *vdev) + + spin_lock_init(&vb->adjustment_lock); + ++ /* ++ * The virtio balloon itself can't wake up the device, but it is ++ * responsible for processing wakeup events passed up from the transport ++ * layer. Wakeup sources don't support nesting/chaining calls, so we use ++ * our own wakeup source to ensure wakeup events are properly handled ++ * without trampling on the transport layer's wakeup source. ++ */ ++ device_set_wakeup_capable(&vb->vdev->dev, true); ++ + virtio_device_ready(vdev); + + if (towards_target(vb)) +diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c +index b655fccaf7733..584af7816532b 100644 +--- a/drivers/virtio/virtio_pci_common.c ++++ b/drivers/virtio/virtio_pci_common.c +@@ -348,8 +348,10 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, + vring_interrupt, 0, + vp_dev->msix_names[msix_vec], + vqs[i]); +- if (err) ++ if (err) { ++ vp_del_vq(vqs[i]); + goto error_find; ++ } + } + return 0; + +diff --git a/drivers/watchdog/bd9576_wdt.c b/drivers/watchdog/bd9576_wdt.c +index 4a20e07fbb699..f00ea1b4e40b6 100644 +--- a/drivers/watchdog/bd9576_wdt.c ++++ b/drivers/watchdog/bd9576_wdt.c +@@ -29,7 +29,6 @@ struct bd9576_wdt_priv { + struct gpio_desc *gpiod_en; + struct device *dev; + struct regmap *regmap; +- bool always_running; + struct watchdog_device wdd; + }; + +@@ -62,10 +61,7 @@ static int bd9576_wdt_stop(struct watchdog_device *wdd) + { + struct bd9576_wdt_priv *priv = watchdog_get_drvdata(wdd); + +- if (!priv->always_running) +- bd9576_wdt_disable(priv); +- else +- set_bit(WDOG_HW_RUNNING, &wdd->status); ++ bd9576_wdt_disable(priv); + + return 0; + } +@@ -264,9 +260,6 @@ static int bd9576_wdt_probe(struct platform_device *pdev) + if (ret) + return ret; + +- priv->always_running = device_property_read_bool(dev->parent, +- "always-running"); +- + watchdog_set_drvdata(&priv->wdd, priv); + + priv->wdd.info = &bd957x_wdt_ident; +@@ -281,9 +274,6 @@ static int bd9576_wdt_probe(struct platform_device *pdev) + + watchdog_stop_on_reboot(&priv->wdd); + +- if (priv->always_running) +- bd9576_wdt_start(&priv->wdd); +- + return devm_watchdog_register_device(dev, &priv->wdd); + } + +diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c +index 688b112e712ba..9f279c0e13a66 100644 +--- a/drivers/watchdog/cpu5wdt.c ++++ b/drivers/watchdog/cpu5wdt.c +@@ -252,7 +252,7 @@ static void cpu5wdt_exit(void) + if (cpu5wdt_device.queue) { + cpu5wdt_device.queue = 0; + wait_for_completion(&cpu5wdt_device.stop); +- del_timer(&cpu5wdt_device.timer); ++ timer_shutdown_sync(&cpu5wdt_device.timer); + } + + misc_deregister(&cpu5wdt_misc); +diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c +index 5d2df008b92a5..34a917221e316 100644 +--- a/drivers/watchdog/sa1100_wdt.c ++++ b/drivers/watchdog/sa1100_wdt.c +@@ -191,9 +191,8 @@ static int sa1100dog_probe(struct platform_device *pdev) + if (!res) + return -ENXIO; + reg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); +- ret = PTR_ERR_OR_ZERO(reg_base); +- if (ret) +- return ret; ++ if (!reg_base) ++ return -ENOMEM; + + clk = clk_get(NULL, "OSTIMER0"); + if (IS_ERR(clk)) { +diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c +index 3205e5d724c8c..1a9ded0cddcb0 100644 +--- a/drivers/xen/xenbus/xenbus_probe.c ++++ b/drivers/xen/xenbus/xenbus_probe.c +@@ -65,13 +65,17 @@ + #include "xenbus.h" + + +-static int xs_init_irq; ++static int xs_init_irq = -1; + int xen_store_evtchn; + EXPORT_SYMBOL_GPL(xen_store_evtchn); + + struct xenstore_domain_interface *xen_store_interface; + EXPORT_SYMBOL_GPL(xen_store_interface); + ++#define XS_INTERFACE_READY \ ++ ((xen_store_interface != NULL) && \ ++ (xen_store_interface->connection == XENSTORE_CONNECTED)) ++ + enum xenstore_init xen_store_domain_type; + EXPORT_SYMBOL_GPL(xen_store_domain_type); + +@@ -751,19 +755,19 @@ static void xenbus_probe(void) + { + xenstored_ready = 1; + +- if (!xen_store_interface) { ++ if (!xen_store_interface) + xen_store_interface = memremap(xen_store_gfn << XEN_PAGE_SHIFT, + XEN_PAGE_SIZE, MEMREMAP_WB); +- /* +- * Now it is safe to free the IRQ used for xenstore late +- * initialization. No need to unbind: it is about to be +- * bound again from xb_init_comms. Note that calling +- * unbind_from_irqhandler now would result in xen_evtchn_close() +- * being called and the event channel not being enabled again +- * afterwards, resulting in missed event notifications. +- */ ++ /* ++ * Now it is safe to free the IRQ used for xenstore late ++ * initialization. No need to unbind: it is about to be ++ * bound again from xb_init_comms. Note that calling ++ * unbind_from_irqhandler now would result in xen_evtchn_close() ++ * being called and the event channel not being enabled again ++ * afterwards, resulting in missed event notifications. ++ */ ++ if (xs_init_irq >= 0) + free_irq(xs_init_irq, &xb_waitq); +- } + + /* + * In the HVM case, xenbus_init() deferred its call to +@@ -822,7 +826,7 @@ static int __init xenbus_probe_initcall(void) + if (xen_store_domain_type == XS_PV || + (xen_store_domain_type == XS_HVM && + !xs_hvm_defer_init_for_callback() && +- xen_store_interface != NULL)) ++ XS_INTERFACE_READY)) + xenbus_probe(); + + /* +@@ -831,7 +835,7 @@ static int __init xenbus_probe_initcall(void) + * started, then probe. It will be triggered when communication + * starts happening, by waiting on xb_waitq. + */ +- if (xen_store_domain_type == XS_LOCAL || xen_store_interface == NULL) { ++ if (xen_store_domain_type == XS_LOCAL || !XS_INTERFACE_READY) { + struct task_struct *probe_task; + + probe_task = kthread_run(xenbus_probe_thread, NULL, +@@ -1014,6 +1018,12 @@ static int __init xenbus_init(void) + xen_store_interface = + memremap(xen_store_gfn << XEN_PAGE_SHIFT, + XEN_PAGE_SIZE, MEMREMAP_WB); ++ if (!xen_store_interface) { ++ pr_err("%s: cannot map HVM_PARAM_STORE_PFN=%llx\n", ++ __func__, v); ++ err = -EINVAL; ++ goto out_error; ++ } + if (xen_store_interface->connection != XENSTORE_CONNECTED) + wait = true; + } +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index d9494b5fc7c18..5f77f9df24760 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -3896,15 +3896,14 @@ static int check_swap_activate(struct swap_info_struct *sis, + struct address_space *mapping = swap_file->f_mapping; + struct inode *inode = mapping->host; + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); +- sector_t cur_lblock; +- sector_t last_lblock; +- sector_t pblock; +- sector_t lowest_pblock = -1; +- sector_t highest_pblock = 0; ++ block_t cur_lblock; ++ block_t last_lblock; ++ block_t pblock; ++ block_t lowest_pblock = -1; ++ block_t highest_pblock = 0; + int nr_extents = 0; +- unsigned long nr_pblocks; ++ unsigned int nr_pblocks; + unsigned int blks_per_sec = BLKS_PER_SEC(sbi); +- unsigned int sec_blks_mask = BLKS_PER_SEC(sbi) - 1; + unsigned int not_aligned = 0; + int ret = 0; + +@@ -3942,8 +3941,8 @@ static int check_swap_activate(struct swap_info_struct *sis, + pblock = map.m_pblk; + nr_pblocks = map.m_len; + +- if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask || +- nr_pblocks & sec_blks_mask || ++ if ((pblock - SM_I(sbi)->main_blkaddr) % blks_per_sec || ++ nr_pblocks % blks_per_sec || + !f2fs_valid_pinned_area(sbi, pblock)) { + bool last_extent = false; + +@@ -4185,7 +4184,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + if (WARN_ON_ONCE(map.m_pblk == COMPRESS_ADDR)) + return -EINVAL; + +- if (map.m_pblk != NULL_ADDR) { ++ if (map.m_flags & F2FS_MAP_MAPPED) { + iomap->length = blks_to_bytes(inode, map.m_len); + iomap->type = IOMAP_MAPPED; + iomap->flags |= IOMAP_F_MERGED; +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index fced2b7652f40..07b3675ea1694 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -2309,7 +2309,7 @@ static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool); + static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, + struct inode *inode, blkcnt_t *count, bool partial) + { +- blkcnt_t diff = 0, release = 0; ++ long long diff = 0, release = 0; + block_t avail_user_block_count; + int ret; + +@@ -2329,26 +2329,27 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, + percpu_counter_add(&sbi->alloc_valid_block_count, (*count)); + + spin_lock(&sbi->stat_lock); +- sbi->total_valid_block_count += (block_t)(*count); +- avail_user_block_count = get_available_block_count(sbi, inode, true); + +- if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) { ++ avail_user_block_count = get_available_block_count(sbi, inode, true); ++ diff = (long long)sbi->total_valid_block_count + *count - ++ avail_user_block_count; ++ if (unlikely(diff > 0)) { + if (!partial) { + spin_unlock(&sbi->stat_lock); ++ release = *count; + goto enospc; + } +- +- diff = sbi->total_valid_block_count - avail_user_block_count; + if (diff > *count) + diff = *count; + *count -= diff; + release = diff; +- sbi->total_valid_block_count -= diff; + if (!*count) { + spin_unlock(&sbi->stat_lock); + goto enospc; + } + } ++ sbi->total_valid_block_count += (block_t)(*count); ++ + spin_unlock(&sbi->stat_lock); + + if (unlikely(release)) { +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 1761ad125f97a..208dedc161d53 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -952,9 +952,14 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + ATTR_GID | ATTR_TIMES_SET)))) + return -EPERM; + +- if ((attr->ia_valid & ATTR_SIZE) && +- !f2fs_is_compress_backend_ready(inode)) +- return -EOPNOTSUPP; ++ if ((attr->ia_valid & ATTR_SIZE)) { ++ if (!f2fs_is_compress_backend_ready(inode)) ++ return -EOPNOTSUPP; ++ if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) && ++ !IS_ALIGNED(attr->ia_size, ++ F2FS_BLK_TO_BYTES(F2FS_I(inode)->i_cluster_size))) ++ return -EINVAL; ++ } + + err = setattr_prepare(idmap, dentry, attr); + if (err) +@@ -1325,6 +1330,9 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode, + f2fs_put_page(psrc, 1); + return PTR_ERR(pdst); + } ++ ++ f2fs_wait_on_page_writeback(pdst, DATA, true, true); ++ + memcpy_page(pdst, 0, psrc, 0, PAGE_SIZE); + set_page_dirty(pdst); + set_page_private_gcing(pdst); +@@ -1817,15 +1825,6 @@ static long f2fs_fallocate(struct file *file, int mode, + (mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE))) + return -EOPNOTSUPP; + +- /* +- * Pinned file should not support partial truncation since the block +- * can be used by applications. +- */ +- if ((f2fs_compressed_file(inode) || f2fs_is_pinned_file(inode)) && +- (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE | +- FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE))) +- return -EOPNOTSUPP; +- + if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | + FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | + FALLOC_FL_INSERT_RANGE)) +@@ -1833,6 +1832,17 @@ static long f2fs_fallocate(struct file *file, int mode, + + inode_lock(inode); + ++ /* ++ * Pinned file should not support partial truncation since the block ++ * can be used by applications. ++ */ ++ if ((f2fs_compressed_file(inode) || f2fs_is_pinned_file(inode)) && ++ (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE | ++ FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE))) { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } ++ + ret = file_modified(file); + if (ret) + goto out; +@@ -2837,7 +2847,8 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in, + goto out; + } + +- if (f2fs_compressed_file(src) || f2fs_compressed_file(dst)) { ++ if (f2fs_compressed_file(src) || f2fs_compressed_file(dst) || ++ f2fs_is_pinned_file(src) || f2fs_is_pinned_file(dst)) { + ret = -EOPNOTSUPP; + goto out_unlock; + } +@@ -3522,9 +3533,6 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg) + if (!f2fs_sb_has_compression(sbi)) + return -EOPNOTSUPP; + +- if (!f2fs_compressed_file(inode)) +- return -EINVAL; +- + if (f2fs_readonly(sbi->sb)) + return -EROFS; + +@@ -3543,7 +3551,8 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg) + goto out; + } + +- if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { ++ if (!f2fs_compressed_file(inode) || ++ is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { + ret = -EINVAL; + goto out; + } +@@ -3570,9 +3579,12 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg) + struct dnode_of_data dn; + pgoff_t end_offset, count; + ++ f2fs_lock_op(sbi); ++ + set_new_dnode(&dn, inode, NULL, NULL, 0); + ret = f2fs_get_dnode_of_data(&dn, page_idx, LOOKUP_NODE); + if (ret) { ++ f2fs_unlock_op(sbi); + if (ret == -ENOENT) { + page_idx = f2fs_get_next_page_offset(&dn, + page_idx); +@@ -3590,6 +3602,8 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg) + + f2fs_put_dnode(&dn); + ++ f2fs_unlock_op(sbi); ++ + if (ret < 0) + break; + +@@ -3641,7 +3655,8 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count, + + while (count) { + int compr_blocks = 0; +- blkcnt_t reserved; ++ blkcnt_t reserved = 0; ++ blkcnt_t to_reserved; + int ret; + + for (i = 0; i < cluster_size; i++) { +@@ -3661,20 +3676,26 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count, + * fails in release_compress_blocks(), so NEW_ADDR + * is a possible case. + */ +- if (blkaddr == NEW_ADDR || +- __is_valid_data_blkaddr(blkaddr)) { ++ if (blkaddr == NEW_ADDR) { ++ reserved++; ++ continue; ++ } ++ if (__is_valid_data_blkaddr(blkaddr)) { + compr_blocks++; + continue; + } + } + +- reserved = cluster_size - compr_blocks; ++ to_reserved = cluster_size - compr_blocks - reserved; + + /* for the case all blocks in cluster were reserved */ +- if (reserved == 1) ++ if (to_reserved == 1) { ++ dn->ofs_in_node += cluster_size; + goto next; ++ } + +- ret = inc_valid_block_count(sbi, dn->inode, &reserved, false); ++ ret = inc_valid_block_count(sbi, dn->inode, ++ &to_reserved, false); + if (unlikely(ret)) + return ret; + +@@ -3685,7 +3706,7 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count, + + f2fs_i_compr_blocks_update(dn->inode, compr_blocks, true); + +- *reserved_blocks += reserved; ++ *reserved_blocks += to_reserved; + next: + count -= cluster_size; + } +@@ -3704,9 +3725,6 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) + if (!f2fs_sb_has_compression(sbi)) + return -EOPNOTSUPP; + +- if (!f2fs_compressed_file(inode)) +- return -EINVAL; +- + if (f2fs_readonly(sbi->sb)) + return -EROFS; + +@@ -3718,7 +3736,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) + + inode_lock(inode); + +- if (!is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { ++ if (!f2fs_compressed_file(inode) || ++ !is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { + ret = -EINVAL; + goto unlock_inode; + } +@@ -3735,9 +3754,12 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) + struct dnode_of_data dn; + pgoff_t end_offset, count; + ++ f2fs_lock_op(sbi); ++ + set_new_dnode(&dn, inode, NULL, NULL, 0); + ret = f2fs_get_dnode_of_data(&dn, page_idx, LOOKUP_NODE); + if (ret) { ++ f2fs_unlock_op(sbi); + if (ret == -ENOENT) { + page_idx = f2fs_get_next_page_offset(&dn, + page_idx); +@@ -3755,6 +3777,8 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg) + + f2fs_put_dnode(&dn); + ++ f2fs_unlock_op(sbi); ++ + if (ret < 0) + break; + +@@ -4119,9 +4143,6 @@ static int f2fs_ioc_decompress_file(struct file *filp) + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + +- if (!f2fs_compressed_file(inode)) +- return -EINVAL; +- + f2fs_balance_fs(sbi, true); + + file_start_write(filp); +@@ -4132,7 +4153,8 @@ static int f2fs_ioc_decompress_file(struct file *filp) + goto out; + } + +- if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { ++ if (!f2fs_compressed_file(inode) || ++ is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { + ret = -EINVAL; + goto out; + } +@@ -4197,9 +4219,6 @@ static int f2fs_ioc_compress_file(struct file *filp) + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + +- if (!f2fs_compressed_file(inode)) +- return -EINVAL; +- + f2fs_balance_fs(sbi, true); + + file_start_write(filp); +@@ -4210,7 +4229,8 @@ static int f2fs_ioc_compress_file(struct file *filp) + goto out; + } + +- if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { ++ if (!f2fs_compressed_file(inode) || ++ is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { + ret = -EINVAL; + goto out; + } +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index 8852814dab7f6..e86c7f01539a7 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1554,10 +1554,15 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + int err; + + inode = f2fs_iget(sb, dni.ino); +- if (IS_ERR(inode) || is_bad_inode(inode) || +- special_file(inode->i_mode)) ++ if (IS_ERR(inode)) + continue; + ++ if (is_bad_inode(inode) || ++ special_file(inode->i_mode)) { ++ iput(inode); ++ continue; ++ } ++ + err = f2fs_gc_pinned_control(inode, gc_type, segno); + if (err == -EAGAIN) { + iput(inode); +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index b3de6d6cdb021..7df5ad84cb5ea 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -1319,6 +1319,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs) + } + if (unlikely(new_ni.blk_addr != NULL_ADDR)) { + err = -EFSCORRUPTED; ++ dec_valid_node_count(sbi, dn->inode, !ofs); + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); + goto fail; +@@ -1345,7 +1346,6 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs) + if (ofs == 0) + inc_valid_inode_count(sbi); + return page; +- + fail: + clear_node_page_dirty(page); + f2fs_put_page(page, 1); +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 4fd76e867e0a2..6474b7338e811 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -3559,6 +3559,8 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, + if (segment_full) { + if (type == CURSEG_COLD_DATA_PINNED && + !((curseg->segno + 1) % sbi->segs_per_sec)) { ++ write_sum_page(sbi, curseg->sum_blk, ++ GET_SUM_BLOCK(sbi, curseg->segno)); + reset_curseg_fields(curseg); + goto skip_new_segment; + } +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 3ec8bb5e68ff5..9eb191b5c4de1 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1813,7 +1813,8 @@ static void fuse_resend(struct fuse_conn *fc) + spin_unlock(&fc->lock); + + list_for_each_entry_safe(req, next, &to_queue, list) { +- __set_bit(FR_PENDING, &req->flags); ++ set_bit(FR_PENDING, &req->flags); ++ clear_bit(FR_SENT, &req->flags); + /* mark the request as resend request */ + req->in.h.unique |= FUSE_UNIQUE_RESEND; + } +diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c +index 267b622d923b1..912ad0a1df021 100644 +--- a/fs/netfs/buffered_write.c ++++ b/fs/netfs/buffered_write.c +@@ -163,7 +163,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, + struct folio *folio; + enum netfs_how_to_modify howto; + enum netfs_folio_trace trace; +- unsigned int bdp_flags = (iocb->ki_flags & IOCB_SYNC) ? 0: BDP_ASYNC; ++ unsigned int bdp_flags = (iocb->ki_flags & IOCB_NOWAIT) ? BDP_ASYNC : 0; + ssize_t written = 0, ret, ret2; + loff_t i_size, pos = iocb->ki_pos, from, to; + size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER; +diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c +index ce8f8934bca51..569ae4ec60845 100644 +--- a/fs/nfs/filelayout/filelayout.c ++++ b/fs/nfs/filelayout/filelayout.c +@@ -883,7 +883,7 @@ filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, + NFS4_MAX_UINT64, + IOMODE_READ, + false, +- GFP_KERNEL); ++ nfs_io_gfp_mask()); + if (IS_ERR(pgio->pg_lseg)) { + pgio->pg_error = PTR_ERR(pgio->pg_lseg); + pgio->pg_lseg = NULL; +@@ -907,7 +907,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, + NFS4_MAX_UINT64, + IOMODE_RW, + false, +- GFP_NOFS); ++ nfs_io_gfp_mask()); + if (IS_ERR(pgio->pg_lseg)) { + pgio->pg_error = PTR_ERR(pgio->pg_lseg); + pgio->pg_lseg = NULL; +diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c +index d0a0956f8a134..cac1157be2c29 100644 +--- a/fs/nfs/fs_context.c ++++ b/fs/nfs/fs_context.c +@@ -1112,9 +1112,12 @@ static int nfs23_parse_monolithic(struct fs_context *fc, + ctx->acdirmax = data->acdirmax; + ctx->need_mount = false; + +- memcpy(sap, &data->addr, sizeof(data->addr)); +- ctx->nfs_server.addrlen = sizeof(data->addr); +- ctx->nfs_server.port = ntohs(data->addr.sin_port); ++ if (!is_remount_fc(fc)) { ++ memcpy(sap, &data->addr, sizeof(data->addr)); ++ ctx->nfs_server.addrlen = sizeof(data->addr); ++ ctx->nfs_server.port = ntohs(data->addr.sin_port); ++ } ++ + if (sap->ss_family != AF_INET || + !nfs_verify_server_address(sap)) + goto out_no_address; +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index 662e86ea3a2dd..5b452411e8fdf 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -2116,6 +2116,7 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred + { + struct nfs_client *clp = server->nfs_client; + struct nfs4_fs_locations *locations = NULL; ++ struct nfs_fattr *fattr; + struct inode *inode; + struct page *page; + int status, result; +@@ -2125,19 +2126,16 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred + (unsigned long long)server->fsid.minor, + clp->cl_hostname); + +- result = 0; + page = alloc_page(GFP_KERNEL); + locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); +- if (page == NULL || locations == NULL) { +- dprintk("<-- %s: no memory\n", __func__); +- goto out; +- } +- locations->fattr = nfs_alloc_fattr(); +- if (locations->fattr == NULL) { ++ fattr = nfs_alloc_fattr(); ++ if (page == NULL || locations == NULL || fattr == NULL) { + dprintk("<-- %s: no memory\n", __func__); ++ result = 0; + goto out; + } + ++ locations->fattr = fattr; + inode = d_inode(server->super->s_root); + result = nfs4_proc_get_locations(server, NFS_FH(inode), locations, + page, cred); +diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c +index 855519713bf79..4085fe30bf481 100644 +--- a/fs/ntfs3/fslog.c ++++ b/fs/ntfs3/fslog.c +@@ -1184,7 +1184,8 @@ static int read_log_page(struct ntfs_log *log, u32 vbo, + static int log_read_rst(struct ntfs_log *log, bool first, + struct restart_info *info) + { +- u32 skip, vbo; ++ u32 skip; ++ u64 vbo; + struct RESTART_HDR *r_page = NULL; + + /* Determine which restart area we are looking for. */ +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index ba5a39a2f957d..90d4e9a9859e4 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -577,13 +577,18 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo, + clear_buffer_uptodate(bh); + + if (is_resident(ni)) { +- ni_lock(ni); +- err = attr_data_read_resident(ni, &folio->page); +- ni_unlock(ni); +- +- if (!err) +- set_buffer_uptodate(bh); ++ bh->b_blocknr = RESIDENT_LCN; + bh->b_size = block_size; ++ if (!folio) { ++ err = 0; ++ } else { ++ ni_lock(ni); ++ err = attr_data_read_resident(ni, &folio->page); ++ ni_unlock(ni); ++ ++ if (!err) ++ set_buffer_uptodate(bh); ++ } + return err; + } + +diff --git a/fs/ntfs3/ntfs.h b/fs/ntfs3/ntfs.h +index 9c7478150a035..3d6143c7abc03 100644 +--- a/fs/ntfs3/ntfs.h ++++ b/fs/ntfs3/ntfs.h +@@ -59,7 +59,7 @@ struct GUID { + struct cpu_str { + u8 len; + u8 unused; +- u16 name[10]; ++ u16 name[]; + }; + + struct le_str { +diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c +index c803c10dd97ef..33aeaaa056d70 100644 +--- a/fs/ocfs2/localalloc.c ++++ b/fs/ocfs2/localalloc.c +@@ -863,14 +863,8 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, + + numfound = bitoff = startoff = 0; + left = le32_to_cpu(alloc->id1.bitmap1.i_total); +- while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left, startoff)) != -1) { +- if (bitoff == left) { +- /* mlog(0, "bitoff (%d) == left", bitoff); */ +- break; +- } +- /* mlog(0, "Found a zero: bitoff = %d, startoff = %d, " +- "numfound = %d\n", bitoff, startoff, numfound);*/ +- ++ while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left, startoff)) < ++ left) { + /* Ok, we found a zero bit... is it contig. or do we + * start over?*/ + if (bitoff == startoff) { +@@ -976,9 +970,9 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, + start = count = 0; + left = le32_to_cpu(alloc->id1.bitmap1.i_total); + +- while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start)) +- != -1) { +- if ((bit_off < left) && (bit_off == start)) { ++ while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start)) < ++ left) { ++ if (bit_off == start) { + count++; + start++; + continue; +@@ -1002,8 +996,7 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, + goto bail; + } + } +- if (bit_off >= left) +- break; ++ + count = 1; + start = bit_off + 1; + } +diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c +index a9d1296d736dc..1fe61974d9f02 100644 +--- a/fs/ocfs2/reservations.c ++++ b/fs/ocfs2/reservations.c +@@ -414,7 +414,7 @@ static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap, + + start = search_start; + while ((offset = ocfs2_find_next_zero_bit(bitmap, resmap->m_bitmap_len, +- start)) != -1) { ++ start)) < resmap->m_bitmap_len) { + /* Search reached end of the region */ + if (offset >= (search_start + search_len)) + break; +diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c +index 166c8918c825a..961998415308d 100644 +--- a/fs/ocfs2/suballoc.c ++++ b/fs/ocfs2/suballoc.c +@@ -1290,10 +1290,8 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, + found = start = best_offset = best_size = 0; + bitmap = bg->bg_bitmap; + +- while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) { +- if (offset == total_bits) +- break; +- ++ while ((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) < ++ total_bits) { + if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) { + /* We found a zero, but we can't use it as it + * hasn't been put to disk yet! */ +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 0f8b4a719237c..02d89a285d0dc 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -327,9 +327,6 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, + struct dentry *newdentry; + int err; + +- if (!attr->hardlink && !IS_POSIXACL(udir)) +- attr->mode &= ~current_umask(); +- + inode_lock_nested(udir, I_MUTEX_PARENT); + newdentry = ovl_create_real(ofs, udir, + ovl_lookup_upper(ofs, dentry->d_name.name, +diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c +index 39277c37185ca..4fb21affe4e11 100644 +--- a/fs/smb/client/cifsfs.c ++++ b/fs/smb/client/cifsfs.c +@@ -1277,7 +1277,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, + struct cifsFileInfo *smb_file_src = src_file->private_data; + struct cifsFileInfo *smb_file_target = dst_file->private_data; + struct cifs_tcon *target_tcon, *src_tcon; +- unsigned long long destend, fstart, fend, new_size; ++ unsigned long long destend, fstart, fend, old_size, new_size; + unsigned int xid; + int rc; + +@@ -1342,6 +1342,9 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, + rc = cifs_flush_folio(target_inode, destend, &fstart, &fend, false); + if (rc) + goto unlock; ++ if (fend > target_cifsi->netfs.zero_point) ++ target_cifsi->netfs.zero_point = fend + 1; ++ old_size = target_cifsi->netfs.remote_i_size; + + /* Discard all the folios that overlap the destination region. */ + cifs_dbg(FYI, "about to discard pages %llx-%llx\n", fstart, fend); +@@ -1354,12 +1357,13 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, + if (target_tcon->ses->server->ops->duplicate_extents) { + rc = target_tcon->ses->server->ops->duplicate_extents(xid, + smb_file_src, smb_file_target, off, len, destoff); +- if (rc == 0 && new_size > i_size_read(target_inode)) { ++ if (rc == 0 && new_size > old_size) { + truncate_setsize(target_inode, new_size); +- netfs_resize_file(&target_cifsi->netfs, new_size, true); + fscache_resize_cookie(cifs_inode_cookie(target_inode), + new_size); + } ++ if (rc == 0 && new_size > target_cifsi->netfs.zero_point) ++ target_cifsi->netfs.zero_point = new_size; + } + + /* force revalidate of size and timestamps of target file now +@@ -1451,6 +1455,8 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, + rc = cifs_flush_folio(target_inode, destend, &fstart, &fend, false); + if (rc) + goto unlock; ++ if (fend > target_cifsi->netfs.zero_point) ++ target_cifsi->netfs.zero_point = fend + 1; + + /* Discard all the folios that overlap the destination region. */ + truncate_inode_pages_range(&target_inode->i_data, fstart, fend); +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 28f0b7d19d534..6fea0aed43461 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -2028,6 +2028,7 @@ smb2_duplicate_extents(const unsigned int xid, + * size will be queried on next revalidate, but it is important + * to make sure that file's cached size is updated immediately + */ ++ netfs_resize_file(netfs_inode(inode), dest_off + len, true); + cifs_setsize(inode, dest_off + len); + } + rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index 2f831a3a91afe..bbf8918417fd8 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -341,7 +341,7 @@ const struct address_space_operations udf_aops = { + */ + int udf_expand_file_adinicb(struct inode *inode) + { +- struct page *page; ++ struct folio *folio; + struct udf_inode_info *iinfo = UDF_I(inode); + int err; + +@@ -357,12 +357,13 @@ int udf_expand_file_adinicb(struct inode *inode) + return 0; + } + +- page = find_or_create_page(inode->i_mapping, 0, GFP_KERNEL); +- if (!page) +- return -ENOMEM; ++ folio = __filemap_get_folio(inode->i_mapping, 0, ++ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_KERNEL); ++ if (IS_ERR(folio)) ++ return PTR_ERR(folio); + +- if (!PageUptodate(page)) +- udf_adinicb_readpage(page); ++ if (!folio_test_uptodate(folio)) ++ udf_adinicb_readpage(&folio->page); + down_write(&iinfo->i_data_sem); + memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00, + iinfo->i_lenAlloc); +@@ -371,22 +372,22 @@ int udf_expand_file_adinicb(struct inode *inode) + iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT; + else + iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; +- set_page_dirty(page); +- unlock_page(page); ++ folio_mark_dirty(folio); ++ folio_unlock(folio); + up_write(&iinfo->i_data_sem); + err = filemap_fdatawrite(inode->i_mapping); + if (err) { + /* Restore everything back so that we don't lose data... */ +- lock_page(page); ++ folio_lock(folio); + down_write(&iinfo->i_data_sem); +- memcpy_to_page(page, 0, iinfo->i_data + iinfo->i_lenEAttr, +- inode->i_size); +- unlock_page(page); ++ memcpy_from_folio(iinfo->i_data + iinfo->i_lenEAttr, ++ folio, 0, inode->i_size); ++ folio_unlock(folio); + iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; + iinfo->i_lenAlloc = inode->i_size; + up_write(&iinfo->i_data_sem); + } +- put_page(page); ++ folio_put(folio); + mark_inode_dirty(inode); + + return err; +diff --git a/include/linux/counter.h b/include/linux/counter.h +index 702e9108bbb44..b767b5c821f58 100644 +--- a/include/linux/counter.h ++++ b/include/linux/counter.h +@@ -359,7 +359,6 @@ struct counter_ops { + * @num_counts: number of Counts specified in @counts + * @ext: optional array of Counter device extensions + * @num_ext: number of Counter device extensions specified in @ext +- * @priv: optional private data supplied by driver + * @dev: internal device structure + * @chrdev: internal character device structure + * @events_list: list of current watching Counter events +diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h +index 297231854ada5..e44913a8200fd 100644 +--- a/include/linux/etherdevice.h ++++ b/include/linux/etherdevice.h +@@ -632,6 +632,14 @@ static inline void eth_skb_pkt_type(struct sk_buff *skb, + } + } + ++static inline struct ethhdr *eth_skb_pull_mac(struct sk_buff *skb) ++{ ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ ++ skb_pull_inline(skb, ETH_HLEN); ++ return eth; ++} ++ + /** + * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame + * @skb: Buffer to pad +diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h +index 6eaa190d0083c..9754f97e71e52 100644 +--- a/include/linux/fortify-string.h ++++ b/include/linux/fortify-string.h +@@ -71,17 +71,30 @@ void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning(" + __ret; \ + }) + +-#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) ++#if defined(__SANITIZE_ADDRESS__) ++ ++#if !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) && !defined(CONFIG_GENERIC_ENTRY) ++extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset); ++extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove); ++extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy); ++#elif defined(CONFIG_KASAN_GENERIC) ++extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(__asan_memset); ++extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(__asan_memmove); ++extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(__asan_memcpy); ++#else /* CONFIG_KASAN_SW_TAGS */ ++extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(__hwasan_memset); ++extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(__hwasan_memmove); ++extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(__hwasan_memcpy); ++#endif ++ + extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr); + extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp); +-extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy); +-extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove); +-extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset); + extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat); + extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy); + extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen); + extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat); + extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy); ++ + #else + + #if defined(__SANITIZE_MEMORY__) +@@ -106,6 +119,7 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) + #define __underlying_strlen __builtin_strlen + #define __underlying_strncat __builtin_strncat + #define __underlying_strncpy __builtin_strncpy ++ + #endif + + /** +diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h +index 223da48a6d18b..94c4edd047e54 100644 +--- a/include/linux/fpga/fpga-bridge.h ++++ b/include/linux/fpga/fpga-bridge.h +@@ -45,6 +45,7 @@ struct fpga_bridge_info { + * @dev: FPGA bridge device + * @mutex: enforces exclusive reference to bridge + * @br_ops: pointer to struct of FPGA bridge ops ++ * @br_ops_owner: module containing the br_ops + * @info: fpga image specific information + * @node: FPGA bridge list node + * @priv: low level driver private date +@@ -54,6 +55,7 @@ struct fpga_bridge { + struct device dev; + struct mutex mutex; /* for exclusive reference to bridge */ + const struct fpga_bridge_ops *br_ops; ++ struct module *br_ops_owner; + struct fpga_image_info *info; + struct list_head node; + void *priv; +@@ -79,10 +81,12 @@ int of_fpga_bridge_get_to_list(struct device_node *np, + struct fpga_image_info *info, + struct list_head *bridge_list); + ++#define fpga_bridge_register(parent, name, br_ops, priv) \ ++ __fpga_bridge_register(parent, name, br_ops, priv, THIS_MODULE) + struct fpga_bridge * +-fpga_bridge_register(struct device *parent, const char *name, +- const struct fpga_bridge_ops *br_ops, +- void *priv); ++__fpga_bridge_register(struct device *parent, const char *name, ++ const struct fpga_bridge_ops *br_ops, void *priv, ++ struct module *owner); + void fpga_bridge_unregister(struct fpga_bridge *br); + + #endif /* _LINUX_FPGA_BRIDGE_H */ +diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h +index 54f63459efd6e..0d4fe068f3d8a 100644 +--- a/include/linux/fpga/fpga-mgr.h ++++ b/include/linux/fpga/fpga-mgr.h +@@ -201,6 +201,7 @@ struct fpga_manager_ops { + * @state: state of fpga manager + * @compat_id: FPGA manager id for compatibility check. + * @mops: pointer to struct of fpga manager ops ++ * @mops_owner: module containing the mops + * @priv: low level driver private date + */ + struct fpga_manager { +@@ -210,6 +211,7 @@ struct fpga_manager { + enum fpga_mgr_states state; + struct fpga_compat_id *compat_id; + const struct fpga_manager_ops *mops; ++ struct module *mops_owner; + void *priv; + }; + +@@ -230,18 +232,30 @@ struct fpga_manager *fpga_mgr_get(struct device *dev); + + void fpga_mgr_put(struct fpga_manager *mgr); + ++#define fpga_mgr_register_full(parent, info) \ ++ __fpga_mgr_register_full(parent, info, THIS_MODULE) + struct fpga_manager * +-fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info); ++__fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, ++ struct module *owner); + ++#define fpga_mgr_register(parent, name, mops, priv) \ ++ __fpga_mgr_register(parent, name, mops, priv, THIS_MODULE) + struct fpga_manager * +-fpga_mgr_register(struct device *parent, const char *name, +- const struct fpga_manager_ops *mops, void *priv); ++__fpga_mgr_register(struct device *parent, const char *name, ++ const struct fpga_manager_ops *mops, void *priv, struct module *owner); ++ + void fpga_mgr_unregister(struct fpga_manager *mgr); + ++#define devm_fpga_mgr_register_full(parent, info) \ ++ __devm_fpga_mgr_register_full(parent, info, THIS_MODULE) + struct fpga_manager * +-devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info); ++__devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, ++ struct module *owner); ++#define devm_fpga_mgr_register(parent, name, mops, priv) \ ++ __devm_fpga_mgr_register(parent, name, mops, priv, THIS_MODULE) + struct fpga_manager * +-devm_fpga_mgr_register(struct device *parent, const char *name, +- const struct fpga_manager_ops *mops, void *priv); ++__devm_fpga_mgr_register(struct device *parent, const char *name, ++ const struct fpga_manager_ops *mops, void *priv, ++ struct module *owner); + + #endif /*_LINUX_FPGA_MGR_H */ +diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h +index 9d4d32909340a..5fbc05fe70a6b 100644 +--- a/include/linux/fpga/fpga-region.h ++++ b/include/linux/fpga/fpga-region.h +@@ -36,6 +36,7 @@ struct fpga_region_info { + * @mgr: FPGA manager + * @info: FPGA image info + * @compat_id: FPGA region id for compatibility check. ++ * @ops_owner: module containing the get_bridges function + * @priv: private data + * @get_bridges: optional function to get bridges to a list + */ +@@ -46,6 +47,7 @@ struct fpga_region { + struct fpga_manager *mgr; + struct fpga_image_info *info; + struct fpga_compat_id *compat_id; ++ struct module *ops_owner; + void *priv; + int (*get_bridges)(struct fpga_region *region); + }; +@@ -58,12 +60,17 @@ fpga_region_class_find(struct device *start, const void *data, + + int fpga_region_program_fpga(struct fpga_region *region); + ++#define fpga_region_register_full(parent, info) \ ++ __fpga_region_register_full(parent, info, THIS_MODULE) + struct fpga_region * +-fpga_region_register_full(struct device *parent, const struct fpga_region_info *info); ++__fpga_region_register_full(struct device *parent, const struct fpga_region_info *info, ++ struct module *owner); + ++#define fpga_region_register(parent, mgr, get_bridges) \ ++ __fpga_region_register(parent, mgr, get_bridges, THIS_MODULE) + struct fpga_region * +-fpga_region_register(struct device *parent, struct fpga_manager *mgr, +- int (*get_bridges)(struct fpga_region *)); ++__fpga_region_register(struct device *parent, struct fpga_manager *mgr, ++ int (*get_bridges)(struct fpga_region *), struct module *owner); + void fpga_region_unregister(struct fpga_region *region); + + #endif /* _FPGA_REGION_H */ +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index c940b329a475f..5e5a9c6774bde 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -10267,9 +10267,9 @@ struct mlx5_ifc_mcam_access_reg_bits { + u8 mfrl[0x1]; + u8 regs_39_to_32[0x8]; + +- u8 regs_31_to_10[0x16]; ++ u8 regs_31_to_11[0x15]; + u8 mtmp[0x1]; +- u8 regs_8_to_0[0x9]; ++ u8 regs_9_to_0[0xa]; + }; + + struct mlx5_ifc_mcam_access_reg_bits1 { +diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h +index 22a07c0900a41..f230a472ccd35 100644 +--- a/include/linux/regulator/driver.h ++++ b/include/linux/regulator/driver.h +@@ -299,6 +299,8 @@ enum regulator_type { + * @vsel_range_reg: Register for range selector when using pickable ranges + * and ``regulator_map_*_voltage_*_pickable`` functions. + * @vsel_range_mask: Mask for register bitfield used for range selector ++ * @range_applied_by_vsel: A flag to indicate that changes to vsel_range_reg ++ * are only effective after vsel_reg is written + * @vsel_reg: Register for selector when using ``regulator_map_*_voltage_*`` + * @vsel_mask: Mask for register bitfield used for selector + * @vsel_step: Specify the resolution of selector stepping when setting +@@ -389,6 +391,7 @@ struct regulator_desc { + + unsigned int vsel_range_reg; + unsigned int vsel_range_mask; ++ bool range_applied_by_vsel; + unsigned int vsel_reg; + unsigned int vsel_mask; + unsigned int vsel_step; +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 4ff48eda3f642..5b1078c160f27 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1174,15 +1174,6 @@ static inline bool skb_dst_is_noref(const struct sk_buff *skb) + return (skb->_skb_refdst & SKB_DST_NOREF) && skb_dst(skb); + } + +-/** +- * skb_rtable - Returns the skb &rtable +- * @skb: buffer +- */ +-static inline struct rtable *skb_rtable(const struct sk_buff *skb) +-{ +- return (struct rtable *)skb_dst(skb); +-} +- + /* For mangling skb->pkt_type from user space side from applications + * such as nft, tc, etc, we only allow a conservative subset of + * possible pkt_types to be set. +diff --git a/include/media/cec.h b/include/media/cec.h +index 10c9cf6058b7e..cc3fcd0496c36 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -258,6 +258,7 @@ struct cec_adapter { + u16 phys_addr; + bool needs_hpd; + bool is_enabled; ++ bool is_claiming_log_addrs; + bool is_configuring; + bool must_reconfigure; + bool is_configured; +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 5277c6d5134ca..970101184cf10 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -1335,8 +1335,7 @@ hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle) + rcu_read_lock(); + + list_for_each_entry_rcu(c, &h->list, list) { +- if (c->type != ISO_LINK || +- !test_bit(HCI_CONN_PA_SYNC, &c->flags)) ++ if (c->type != ISO_LINK) + continue; + + if (c->sync_handle == sync_handle) { +diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h +index 6d1c8541183db..3a9001a042a5c 100644 +--- a/include/net/dst_ops.h ++++ b/include/net/dst_ops.h +@@ -24,7 +24,7 @@ struct dst_ops { + void (*destroy)(struct dst_entry *); + void (*ifdown)(struct dst_entry *, + struct net_device *dev); +- struct dst_entry * (*negative_advice)(struct dst_entry *); ++ void (*negative_advice)(struct sock *sk, struct dst_entry *); + void (*link_failure)(struct sk_buff *); + void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb, u32 mtu, +diff --git a/include/net/ip.h b/include/net/ip.h +index 25cb688bdc623..6d735e00d3f3e 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -423,7 +423,7 @@ int ip_decrease_ttl(struct iphdr *iph) + + static inline int ip_mtu_locked(const struct dst_entry *dst) + { +- const struct rtable *rt = (const struct rtable *)dst; ++ const struct rtable *rt = dst_rtable(dst); + + return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU); + } +@@ -461,7 +461,7 @@ static inline bool ip_sk_ignore_df(const struct sock *sk) + static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, + bool forwarding) + { +- const struct rtable *rt = container_of(dst, struct rtable, dst); ++ const struct rtable *rt = dst_rtable(dst); + struct net *net = dev_net(dst->dev); + unsigned int mtu; + +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index 323c94f1845b9..73524fa0c064b 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -234,9 +234,11 @@ struct fib6_result { + for (rt = (w)->leaf; rt; \ + rt = rcu_dereference_protected(rt->fib6_next, 1)) + +-static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) ++#define dst_rt6_info(_ptr) container_of_const(_ptr, struct rt6_info, dst) ++ ++static inline struct inet6_dev *ip6_dst_idev(const struct dst_entry *dst) + { +- return ((struct rt6_info *)dst)->rt6i_idev; ++ return dst_rt6_info(dst)->rt6i_idev; + } + + static inline bool fib6_requires_src(const struct fib6_info *rt) +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h +index a30c6aa9e5cf3..a18ed24fed948 100644 +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -210,12 +210,11 @@ void rt6_uncached_list_del(struct rt6_info *rt); + static inline const struct rt6_info *skb_rt6_info(const struct sk_buff *skb) + { + const struct dst_entry *dst = skb_dst(skb); +- const struct rt6_info *rt6 = NULL; + + if (dst) +- rt6 = container_of(dst, struct rt6_info, dst); ++ return dst_rt6_info(dst); + +- return rt6; ++ return NULL; + } + + /* +@@ -227,7 +226,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, + { + struct ipv6_pinfo *np = inet6_sk(sk); + +- np->dst_cookie = rt6_get_cookie((struct rt6_info *)dst); ++ np->dst_cookie = rt6_get_cookie(dst_rt6_info(dst)); + sk_setup_caps(sk, dst); + np->daddr_cache = daddr; + #ifdef CONFIG_IPV6_SUBTREES +@@ -240,7 +239,7 @@ void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst, + + static inline bool ipv6_unicast_destination(const struct sk_buff *skb) + { +- struct rt6_info *rt = (struct rt6_info *) skb_dst(skb); ++ const struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + + return rt->rt6i_flags & RTF_LOCAL; + } +@@ -248,7 +247,7 @@ static inline bool ipv6_unicast_destination(const struct sk_buff *skb) + static inline bool ipv6_anycast_destination(const struct dst_entry *dst, + const struct in6_addr *daddr) + { +- struct rt6_info *rt = (struct rt6_info *)dst; ++ const struct rt6_info *rt = dst_rt6_info(dst); + + return rt->rt6i_flags & RTF_ANYCAST || + (rt->rt6i_dst.plen < 127 && +diff --git a/include/net/route.h b/include/net/route.h +index d4a0147942f1a..af55401aa8f40 100644 +--- a/include/net/route.h ++++ b/include/net/route.h +@@ -77,6 +77,17 @@ struct rtable { + rt_pmtu:31; + }; + ++#define dst_rtable(_ptr) container_of_const(_ptr, struct rtable, dst) ++ ++/** ++ * skb_rtable - Returns the skb &rtable ++ * @skb: buffer ++ */ ++static inline struct rtable *skb_rtable(const struct sk_buff *skb) ++{ ++ return dst_rtable(skb_dst(skb)); ++} ++ + static inline bool rt_is_input_route(const struct rtable *rt) + { + return rt->rt_is_input != 0; +diff --git a/include/net/sock.h b/include/net/sock.h +index b4b553df7870c..944f71a8ab223 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -2134,17 +2134,10 @@ sk_dst_get(const struct sock *sk) + + static inline void __dst_negative_advice(struct sock *sk) + { +- struct dst_entry *ndst, *dst = __sk_dst_get(sk); ++ struct dst_entry *dst = __sk_dst_get(sk); + +- if (dst && dst->ops->negative_advice) { +- ndst = dst->ops->negative_advice(dst); +- +- if (ndst != dst) { +- rcu_assign_pointer(sk->sk_dst_cache, ndst); +- sk_tx_queue_clear(sk); +- WRITE_ONCE(sk->sk_dst_pending_confirm, 0); +- } +- } ++ if (dst && dst->ops->negative_advice) ++ dst->ops->negative_advice(sk, dst); + } + + static inline void dst_negative_advice(struct sock *sk) +diff --git a/include/sound/tas2781-dsp.h b/include/sound/tas2781-dsp.h +index ea9af2726a53f..7fba7ea26a4b0 100644 +--- a/include/sound/tas2781-dsp.h ++++ b/include/sound/tas2781-dsp.h +@@ -2,7 +2,7 @@ + // + // ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier + // +-// Copyright (C) 2022 - 2023 Texas Instruments Incorporated ++// Copyright (C) 2022 - 2024 Texas Instruments Incorporated + // https://www.ti.com + // + // The TAS2781 driver implements a flexible and configurable +@@ -13,8 +13,8 @@ + // Author: Kevin Lu <kevin-lu@ti.com> + // + +-#ifndef __TASDEVICE_DSP_H__ +-#define __TASDEVICE_DSP_H__ ++#ifndef __TAS2781_DSP_H__ ++#define __TAS2781_DSP_H__ + + #define MAIN_ALL_DEVICES 0x0d + #define MAIN_DEVICE_A 0x01 +@@ -180,7 +180,6 @@ void tasdevice_calbin_remove(void *context); + int tasdevice_select_tuningprm_cfg(void *context, int prm, + int cfg_no, int rca_conf_no); + int tasdevice_prmg_load(void *context, int prm_no); +-int tasdevice_prmg_calibdata_load(void *context, int prm_no); + void tasdevice_tuning_switch(void *context, int state); + int tas2781_load_calibration(void *context, char *file_name, + unsigned short i); +diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h +index cd84227f1b42f..5402f77ee8594 100644 +--- a/include/uapi/drm/nouveau_drm.h ++++ b/include/uapi/drm/nouveau_drm.h +@@ -68,6 +68,13 @@ extern "C" { + */ + #define NOUVEAU_GETPARAM_VRAM_USED 19 + ++/* ++ * NOUVEAU_GETPARAM_HAS_VMA_TILEMODE ++ * ++ * Query whether tile mode and PTE kind are accepted with VM allocs or not. ++ */ ++#define NOUVEAU_GETPARAM_HAS_VMA_TILEMODE 20 ++ + struct drm_nouveau_getparam { + __u64 param; + __u64 value; +diff --git a/init/Kconfig b/init/Kconfig +index 664bedb9a71fb..459f44ef7cc94 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -743,8 +743,8 @@ config LOG_CPU_MAX_BUF_SHIFT + int "CPU kernel log buffer size contribution (13 => 8 KB, 17 => 128KB)" + depends on SMP + range 0 21 +- default 12 if !BASE_SMALL +- default 0 if BASE_SMALL ++ default 0 if BASE_SMALL != 0 ++ default 12 + depends on PRINTK + help + This option allows to increase the default ring buffer size +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 2c90b1eb12e2c..8a29309db4245 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -8845,7 +8845,8 @@ static bool may_update_sockmap(struct bpf_verifier_env *env, int func_id) + enum bpf_attach_type eatype = env->prog->expected_attach_type; + enum bpf_prog_type type = resolve_prog_type(env->prog); + +- if (func_id != BPF_FUNC_map_update_elem) ++ if (func_id != BPF_FUNC_map_update_elem && ++ func_id != BPF_FUNC_map_delete_elem) + return false; + + /* It's not possible to get access to a locked struct sock in these +@@ -8856,6 +8857,11 @@ static bool may_update_sockmap(struct bpf_verifier_env *env, int func_id) + if (eatype == BPF_TRACE_ITER) + return true; + break; ++ case BPF_PROG_TYPE_SOCK_OPS: ++ /* map_update allowed only via dedicated helpers with event type checks */ ++ if (func_id == BPF_FUNC_map_delete_elem) ++ return true; ++ break; + case BPF_PROG_TYPE_SOCKET_FILTER: + case BPF_PROG_TYPE_SCHED_CLS: + case BPF_PROG_TYPE_SCHED_ACT: +@@ -8951,7 +8957,6 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, + case BPF_MAP_TYPE_SOCKMAP: + if (func_id != BPF_FUNC_sk_redirect_map && + func_id != BPF_FUNC_sock_map_update && +- func_id != BPF_FUNC_map_delete_elem && + func_id != BPF_FUNC_msg_redirect_map && + func_id != BPF_FUNC_sk_select_reuseport && + func_id != BPF_FUNC_map_lookup_elem && +@@ -8961,7 +8966,6 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, + case BPF_MAP_TYPE_SOCKHASH: + if (func_id != BPF_FUNC_sk_redirect_hash && + func_id != BPF_FUNC_sock_hash_update && +- func_id != BPF_FUNC_map_delete_elem && + func_id != BPF_FUNC_msg_redirect_hash && + func_id != BPF_FUNC_sk_select_reuseport && + func_id != BPF_FUNC_map_lookup_elem && +diff --git a/kernel/dma/map_benchmark.c b/kernel/dma/map_benchmark.c +index 02205ab53b7e9..f7f3d14fa69a7 100644 +--- a/kernel/dma/map_benchmark.c ++++ b/kernel/dma/map_benchmark.c +@@ -101,7 +101,6 @@ static int do_map_benchmark(struct map_benchmark_data *map) + struct task_struct **tsk; + int threads = map->bparam.threads; + int node = map->bparam.node; +- const cpumask_t *cpu_mask = cpumask_of_node(node); + u64 loops; + int ret = 0; + int i; +@@ -118,11 +117,13 @@ static int do_map_benchmark(struct map_benchmark_data *map) + if (IS_ERR(tsk[i])) { + pr_err("create dma_map thread failed\n"); + ret = PTR_ERR(tsk[i]); ++ while (--i >= 0) ++ kthread_stop(tsk[i]); + goto out; + } + + if (node != NUMA_NO_NODE) +- kthread_bind_mask(tsk[i], cpu_mask); ++ kthread_bind_mask(tsk[i], cpumask_of_node(node)); + } + + /* clear the old value in the previous benchmark */ +@@ -139,13 +140,17 @@ static int do_map_benchmark(struct map_benchmark_data *map) + + msleep_interruptible(map->bparam.seconds * 1000); + +- /* wait for the completion of benchmark threads */ ++ /* wait for the completion of all started benchmark threads */ + for (i = 0; i < threads; i++) { +- ret = kthread_stop(tsk[i]); +- if (ret) +- goto out; ++ int kthread_ret = kthread_stop_put(tsk[i]); ++ ++ if (kthread_ret) ++ ret = kthread_ret; + } + ++ if (ret) ++ goto out; ++ + loops = atomic64_read(&map->loops); + if (likely(loops > 0)) { + u64 map_variance, unmap_variance; +@@ -170,8 +175,6 @@ static int do_map_benchmark(struct map_benchmark_data *map) + } + + out: +- for (i = 0; i < threads; i++) +- put_task_struct(tsk[i]); + put_device(map->dev); + kfree(tsk); + return ret; +@@ -208,7 +211,8 @@ static long map_benchmark_ioctl(struct file *file, unsigned int cmd, + } + + if (map->bparam.node != NUMA_NO_NODE && +- !node_possible(map->bparam.node)) { ++ (map->bparam.node < 0 || map->bparam.node >= MAX_NUMNODES || ++ !node_possible(map->bparam.node))) { + pr_err("invalid numa node\n"); + return -EINVAL; + } +diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh +index 6d443ea22bb73..4ba5fd3d73ae2 100755 +--- a/kernel/gen_kheaders.sh ++++ b/kernel/gen_kheaders.sh +@@ -14,7 +14,12 @@ include/ + arch/$SRCARCH/include/ + " + +-type cpio > /dev/null ++if ! command -v cpio >/dev/null; then ++ echo >&2 "***" ++ echo >&2 "*** 'cpio' could not be found." ++ echo >&2 "***" ++ exit 1 ++fi + + # Support incremental builds by skipping archive generation + # if timestamps of files being archived are not changed. +diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c +index 1ed2b1739363b..5ecd072a34fe7 100644 +--- a/kernel/irq/cpuhotplug.c ++++ b/kernel/irq/cpuhotplug.c +@@ -69,6 +69,14 @@ static bool migrate_one_irq(struct irq_desc *desc) + return false; + } + ++ /* ++ * Complete an eventually pending irq move cleanup. If this ++ * interrupt was moved in hard irq context, then the vectors need ++ * to be cleaned up. It can't wait until this interrupt actually ++ * happens and this CPU was involved. ++ */ ++ irq_force_complete_move(desc); ++ + /* + * No move required, if: + * - Interrupt is per cpu +@@ -87,14 +95,6 @@ static bool migrate_one_irq(struct irq_desc *desc) + return false; + } + +- /* +- * Complete an eventually pending irq move cleanup. If this +- * interrupt was moved in hard irq context, then the vectors need +- * to be cleaned up. It can't wait until this interrupt actually +- * happens and this CPU was involved. +- */ +- irq_force_complete_move(desc); +- + /* + * If there is a setaffinity pending, then try to reuse the pending + * mask, so the last change of the affinity does not get lost. If +diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c +index 2f68e93fff0bc..df0745a42a3f3 100644 +--- a/kernel/trace/rv/rv.c ++++ b/kernel/trace/rv/rv.c +@@ -245,6 +245,7 @@ static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync) + + /** + * rv_disable_monitor - disable a given runtime monitor ++ * @mdef: Pointer to the monitor definition structure. + * + * Returns 0 on success. + */ +@@ -256,6 +257,7 @@ int rv_disable_monitor(struct rv_monitor_def *mdef) + + /** + * rv_enable_monitor - enable a given runtime monitor ++ * @mdef: Pointer to the monitor definition structure. + * + * Returns 0 on success, error otherwise. + */ +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +index 42bc0f3622263..1a7e7cf944938 100644 +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -553,6 +553,10 @@ static int parse_btf_field(char *fieldname, const struct btf_type *type, + anon_offs = 0; + field = btf_find_struct_member(ctx->btf, type, fieldname, + &anon_offs); ++ if (IS_ERR(field)) { ++ trace_probe_log_err(ctx->offset, BAD_BTF_TID); ++ return PTR_ERR(field); ++ } + if (!field) { + trace_probe_log_err(ctx->offset, NO_BTF_FIELD); + return -ENOENT; +diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan +index e81e1ac4a919b..bdda600f8dfbe 100644 +--- a/lib/Kconfig.ubsan ++++ b/lib/Kconfig.ubsan +@@ -4,6 +4,7 @@ config ARCH_HAS_UBSAN + + menuconfig UBSAN + bool "Undefined behaviour sanity checker" ++ depends on ARCH_HAS_UBSAN + help + This option enables the Undefined Behaviour sanity checker. + Compile-time instrumentation is used to detect various undefined +diff --git a/lib/strcat_kunit.c b/lib/strcat_kunit.c +index e21be95514afa..ca09f7f0e6a26 100644 +--- a/lib/strcat_kunit.c ++++ b/lib/strcat_kunit.c +@@ -10,7 +10,7 @@ + + static volatile int unconst; + +-static void strcat_test(struct kunit *test) ++static void test_strcat(struct kunit *test) + { + char dest[8]; + +@@ -29,7 +29,7 @@ static void strcat_test(struct kunit *test) + KUNIT_EXPECT_STREQ(test, dest, "fourAB"); + } + +-static void strncat_test(struct kunit *test) ++static void test_strncat(struct kunit *test) + { + char dest[8]; + +@@ -56,7 +56,7 @@ static void strncat_test(struct kunit *test) + KUNIT_EXPECT_STREQ(test, dest, "fourAB"); + } + +-static void strlcat_test(struct kunit *test) ++static void test_strlcat(struct kunit *test) + { + char dest[8] = ""; + int len = sizeof(dest) + unconst; +@@ -88,9 +88,9 @@ static void strlcat_test(struct kunit *test) + } + + static struct kunit_case strcat_test_cases[] = { +- KUNIT_CASE(strcat_test), +- KUNIT_CASE(strncat_test), +- KUNIT_CASE(strlcat_test), ++ KUNIT_CASE(test_strcat), ++ KUNIT_CASE(test_strncat), ++ KUNIT_CASE(test_strlcat), + {} + }; + +diff --git a/lib/string_kunit.c b/lib/string_kunit.c +index eabf025cf77c9..dd19bd7748aa2 100644 +--- a/lib/string_kunit.c ++++ b/lib/string_kunit.c +@@ -11,6 +11,12 @@ + #include <linux/slab.h> + #include <linux/string.h> + ++#define STRCMP_LARGE_BUF_LEN 2048 ++#define STRCMP_CHANGE_POINT 1337 ++#define STRCMP_TEST_EXPECT_EQUAL(test, fn, ...) KUNIT_EXPECT_EQ(test, fn(__VA_ARGS__), 0) ++#define STRCMP_TEST_EXPECT_LOWER(test, fn, ...) KUNIT_EXPECT_LT(test, fn(__VA_ARGS__), 0) ++#define STRCMP_TEST_EXPECT_GREATER(test, fn, ...) KUNIT_EXPECT_GT(test, fn(__VA_ARGS__), 0) ++ + static void test_memset16(struct kunit *test) + { + unsigned i, j, k; +@@ -179,6 +185,147 @@ static void test_strspn(struct kunit *test) + } + } + ++static char strcmp_buffer1[STRCMP_LARGE_BUF_LEN]; ++static char strcmp_buffer2[STRCMP_LARGE_BUF_LEN]; ++ ++static void strcmp_fill_buffers(char fill1, char fill2) ++{ ++ memset(strcmp_buffer1, fill1, STRCMP_LARGE_BUF_LEN); ++ memset(strcmp_buffer2, fill2, STRCMP_LARGE_BUF_LEN); ++ strcmp_buffer1[STRCMP_LARGE_BUF_LEN - 1] = 0; ++ strcmp_buffer2[STRCMP_LARGE_BUF_LEN - 1] = 0; ++} ++ ++static void test_strcmp(struct kunit *test) ++{ ++ /* Equal strings */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strcmp, "Hello, Kernel!", "Hello, Kernel!"); ++ /* First string is lexicographically less than the second */ ++ STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Hello, KUnit!", "Hello, Kernel!"); ++ /* First string is lexicographically larger than the second */ ++ STRCMP_TEST_EXPECT_GREATER(test, strcmp, "Hello, Kernel!", "Hello, KUnit!"); ++ /* Empty string is always lexicographically less than any non-empty string */ ++ STRCMP_TEST_EXPECT_LOWER(test, strcmp, "", "Non-empty string"); ++ /* Two empty strings should be equal */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strcmp, "", ""); ++ /* Compare two strings which have only one char difference */ ++ STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Abacaba", "Abadaba"); ++ /* Compare two strings which have the same prefix*/ ++ STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Just a string", "Just a string and something else"); ++} ++ ++static void test_strcmp_long_strings(struct kunit *test) ++{ ++ strcmp_fill_buffers('B', 'B'); ++ STRCMP_TEST_EXPECT_EQUAL(test, strcmp, strcmp_buffer1, strcmp_buffer2); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'A'; ++ STRCMP_TEST_EXPECT_LOWER(test, strcmp, strcmp_buffer1, strcmp_buffer2); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C'; ++ STRCMP_TEST_EXPECT_GREATER(test, strcmp, strcmp_buffer1, strcmp_buffer2); ++} ++ ++static void test_strncmp(struct kunit *test) ++{ ++ /* Equal strings */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Hello, KUnit!", "Hello, KUnit!", 13); ++ /* First string is lexicographically less than the second */ ++ STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Hello, KUnit!", "Hello, Kernel!", 13); ++ /* Result is always 'equal' when count = 0 */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Hello, Kernel!", "Hello, KUnit!", 0); ++ /* Strings with common prefix are equal if count = length of prefix */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Abacaba", "Abadaba", 3); ++ /* Strings with common prefix are not equal when count = length of prefix + 1 */ ++ STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Abacaba", "Abadaba", 4); ++ /* If one string is a prefix of another, the shorter string is lexicographically smaller */ ++ STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Just a string", "Just a string and something else", ++ strlen("Just a string and something else")); ++ /* ++ * If one string is a prefix of another, and we check first length ++ * of prefix chars, the result is 'equal' ++ */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Just a string", "Just a string and something else", ++ strlen("Just a string")); ++} ++ ++static void test_strncmp_long_strings(struct kunit *test) ++{ ++ strcmp_fill_buffers('B', 'B'); ++ STRCMP_TEST_EXPECT_EQUAL(test, strncmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_LARGE_BUF_LEN); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'A'; ++ STRCMP_TEST_EXPECT_LOWER(test, strncmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_LARGE_BUF_LEN); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C'; ++ STRCMP_TEST_EXPECT_GREATER(test, strncmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_LARGE_BUF_LEN); ++ /* the strings are equal up to STRCMP_CHANGE_POINT */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_CHANGE_POINT); ++ STRCMP_TEST_EXPECT_GREATER(test, strncmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_CHANGE_POINT + 1); ++} ++ ++static void test_strcasecmp(struct kunit *test) ++{ ++ /* Same strings in different case should be equal */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "Hello, Kernel!", "HeLLO, KErNeL!"); ++ /* Empty strings should be equal */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "", ""); ++ /* Despite ascii code for 'a' is larger than ascii code for 'B', 'a' < 'B' */ ++ STRCMP_TEST_EXPECT_LOWER(test, strcasecmp, "a", "B"); ++ STRCMP_TEST_EXPECT_GREATER(test, strcasecmp, "B", "a"); ++ /* Special symbols and numbers should be processed correctly */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "-+**.1230ghTTT~^", "-+**.1230Ghttt~^"); ++} ++ ++static void test_strcasecmp_long_strings(struct kunit *test) ++{ ++ strcmp_fill_buffers('b', 'B'); ++ STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, strcmp_buffer1, strcmp_buffer2); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'a'; ++ STRCMP_TEST_EXPECT_LOWER(test, strcasecmp, strcmp_buffer1, strcmp_buffer2); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C'; ++ STRCMP_TEST_EXPECT_GREATER(test, strcasecmp, strcmp_buffer1, strcmp_buffer2); ++} ++ ++static void test_strncasecmp(struct kunit *test) ++{ ++ /* Same strings in different case should be equal */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "AbAcAbA", "Abacaba", strlen("Abacaba")); ++ /* strncasecmp should check 'count' chars only */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "AbaCaBa", "abaCaDa", 5); ++ STRCMP_TEST_EXPECT_LOWER(test, strncasecmp, "a", "B", 1); ++ STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, "B", "a", 1); ++ /* Result is always 'equal' when count = 0 */ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "Abacaba", "Not abacaba", 0); ++} ++ ++static void test_strncasecmp_long_strings(struct kunit *test) ++{ ++ strcmp_fill_buffers('b', 'B'); ++ STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_LARGE_BUF_LEN); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'a'; ++ STRCMP_TEST_EXPECT_LOWER(test, strncasecmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_LARGE_BUF_LEN); ++ ++ strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C'; ++ STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_LARGE_BUF_LEN); ++ ++ STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_CHANGE_POINT); ++ STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, strcmp_buffer1, ++ strcmp_buffer2, STRCMP_CHANGE_POINT + 1); ++} ++ + static struct kunit_case string_test_cases[] = { + KUNIT_CASE(test_memset16), + KUNIT_CASE(test_memset32), +@@ -186,6 +333,14 @@ static struct kunit_case string_test_cases[] = { + KUNIT_CASE(test_strchr), + KUNIT_CASE(test_strnchr), + KUNIT_CASE(test_strspn), ++ KUNIT_CASE(test_strcmp), ++ KUNIT_CASE(test_strcmp_long_strings), ++ KUNIT_CASE(test_strncmp), ++ KUNIT_CASE(test_strncmp_long_strings), ++ KUNIT_CASE(test_strcasecmp), ++ KUNIT_CASE(test_strcasecmp_long_strings), ++ KUNIT_CASE(test_strncasecmp), ++ KUNIT_CASE(test_strncasecmp_long_strings), + {} + }; + +diff --git a/lib/strscpy_kunit.c b/lib/strscpy_kunit.c +index a6b6344354ed5..b6d1d93a88832 100644 +--- a/lib/strscpy_kunit.c ++++ b/lib/strscpy_kunit.c +@@ -8,22 +8,23 @@ + #include <kunit/test.h> + #include <linux/string.h> + +-/* +- * tc() - Run a specific test case. ++/** ++ * strscpy_check() - Run a specific test case. ++ * @test: KUnit test context pointer + * @src: Source string, argument to strscpy_pad() + * @count: Size of destination buffer, argument to strscpy_pad() + * @expected: Expected return value from call to strscpy_pad() +- * @terminator: 1 if there should be a terminating null byte 0 otherwise. + * @chars: Number of characters from the src string expected to be + * written to the dst buffer. ++ * @terminator: 1 if there should be a terminating null byte 0 otherwise. + * @pad: Number of pad characters expected (in the tail of dst buffer). + * (@pad does not include the null terminator byte.) + * + * Calls strscpy_pad() and verifies the return value and state of the + * destination buffer after the call returns. + */ +-static void tc(struct kunit *test, char *src, int count, int expected, +- int chars, int terminator, int pad) ++static void strscpy_check(struct kunit *test, char *src, int count, ++ int expected, int chars, int terminator, int pad) + { + int nr_bytes_poison; + int max_expected; +@@ -79,12 +80,12 @@ static void tc(struct kunit *test, char *src, int count, int expected, + } + } + +-static void strscpy_test(struct kunit *test) ++static void test_strscpy(struct kunit *test) + { + char dest[8]; + + /* +- * tc() uses a destination buffer of size 6 and needs at ++ * strscpy_check() uses a destination buffer of size 6 and needs at + * least 2 characters spare (one for null and one to check for + * overflow). This means we should only call tc() with + * strings up to a maximum of 4 characters long and 'count' +@@ -92,27 +93,27 @@ static void strscpy_test(struct kunit *test) + * the buffer size in tc(). + */ + +- /* tc(test, src, count, expected, chars, terminator, pad) */ +- tc(test, "a", 0, -E2BIG, 0, 0, 0); +- tc(test, "", 0, -E2BIG, 0, 0, 0); ++ /* strscpy_check(test, src, count, expected, chars, terminator, pad) */ ++ strscpy_check(test, "a", 0, -E2BIG, 0, 0, 0); ++ strscpy_check(test, "", 0, -E2BIG, 0, 0, 0); + +- tc(test, "a", 1, -E2BIG, 0, 1, 0); +- tc(test, "", 1, 0, 0, 1, 0); ++ strscpy_check(test, "a", 1, -E2BIG, 0, 1, 0); ++ strscpy_check(test, "", 1, 0, 0, 1, 0); + +- tc(test, "ab", 2, -E2BIG, 1, 1, 0); +- tc(test, "a", 2, 1, 1, 1, 0); +- tc(test, "", 2, 0, 0, 1, 1); ++ strscpy_check(test, "ab", 2, -E2BIG, 1, 1, 0); ++ strscpy_check(test, "a", 2, 1, 1, 1, 0); ++ strscpy_check(test, "", 2, 0, 0, 1, 1); + +- tc(test, "abc", 3, -E2BIG, 2, 1, 0); +- tc(test, "ab", 3, 2, 2, 1, 0); +- tc(test, "a", 3, 1, 1, 1, 1); +- tc(test, "", 3, 0, 0, 1, 2); ++ strscpy_check(test, "abc", 3, -E2BIG, 2, 1, 0); ++ strscpy_check(test, "ab", 3, 2, 2, 1, 0); ++ strscpy_check(test, "a", 3, 1, 1, 1, 1); ++ strscpy_check(test, "", 3, 0, 0, 1, 2); + +- tc(test, "abcd", 4, -E2BIG, 3, 1, 0); +- tc(test, "abc", 4, 3, 3, 1, 0); +- tc(test, "ab", 4, 2, 2, 1, 1); +- tc(test, "a", 4, 1, 1, 1, 2); +- tc(test, "", 4, 0, 0, 1, 3); ++ strscpy_check(test, "abcd", 4, -E2BIG, 3, 1, 0); ++ strscpy_check(test, "abc", 4, 3, 3, 1, 0); ++ strscpy_check(test, "ab", 4, 2, 2, 1, 1); ++ strscpy_check(test, "a", 4, 1, 1, 1, 2); ++ strscpy_check(test, "", 4, 0, 0, 1, 3); + + /* Compile-time-known source strings. */ + KUNIT_EXPECT_EQ(test, strscpy(dest, "", ARRAY_SIZE(dest)), 0); +@@ -127,7 +128,7 @@ static void strscpy_test(struct kunit *test) + } + + static struct kunit_case strscpy_test_cases[] = { +- KUNIT_CASE(strscpy_test), ++ KUNIT_CASE(test_strscpy), + {} + }; + +diff --git a/net/atm/clip.c b/net/atm/clip.c +index 294cb9efe3d38..015fb679be425 100644 +--- a/net/atm/clip.c ++++ b/net/atm/clip.c +@@ -345,7 +345,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb, + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } +- rt = (struct rtable *) dst; ++ rt = dst_rtable(dst); + if (rt->rt_gw_family == AF_INET) + daddr = &rt->rt_gw4; + else +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 27520a8a486f3..50cfec8ccac4f 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -133,7 +133,7 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev, + struct in6_addr *daddr, + struct sk_buff *skb) + { +- struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); ++ struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + int count = atomic_read(&dev->peer_count); + const struct in6_addr *nexthop; + struct lowpan_peer *peer; +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index cce73749f2dce..1ed734a7fb313 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -1,7 +1,7 @@ + /* + BlueZ - Bluetooth protocol stack for Linux + Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. +- Copyright 2023 NXP ++ Copyright 2023-2024 NXP + + Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> + +@@ -6359,14 +6359,16 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, + if (!(flags & HCI_PROTO_DEFER)) + goto unlock; + +- if (ev->status) { +- /* Add connection to indicate the failed PA sync event */ +- pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY, +- HCI_ROLE_SLAVE); ++ /* Add connection to indicate PA sync event */ ++ pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY, ++ HCI_ROLE_SLAVE); + +- if (!pa_sync) +- goto unlock; ++ if (IS_ERR(pa_sync)) ++ goto unlock; ++ ++ pa_sync->sync_handle = le16_to_cpu(ev->handle); + ++ if (ev->status) { + set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags); + + /* Notify iso layer */ +@@ -6383,6 +6385,7 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data, + struct hci_ev_le_per_adv_report *ev = data; + int mask = hdev->link_mode; + __u8 flags = 0; ++ struct hci_conn *pa_sync; + + bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle)); + +@@ -6390,8 +6393,28 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data, + + mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags); + if (!(mask & HCI_LM_ACCEPT)) +- hci_le_pa_term_sync(hdev, ev->sync_handle); ++ goto unlock; ++ ++ if (!(flags & HCI_PROTO_DEFER)) ++ goto unlock; ++ ++ pa_sync = hci_conn_hash_lookup_pa_sync_handle ++ (hdev, ++ le16_to_cpu(ev->sync_handle)); + ++ if (!pa_sync) ++ goto unlock; ++ ++ if (ev->data_status == LE_PA_DATA_COMPLETE && ++ !test_and_set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags)) { ++ /* Notify iso layer */ ++ hci_connect_cfm(pa_sync, 0); ++ ++ /* Notify MGMT layer */ ++ mgmt_device_connected(hdev, pa_sync, NULL, 0); ++ } ++ ++unlock: + hci_dev_unlock(hdev); + } + +@@ -6926,10 +6949,8 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data, + hci_dev_lock(hdev); + + mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags); +- if (!(mask & HCI_LM_ACCEPT)) { +- hci_le_pa_term_sync(hdev, ev->sync_handle); ++ if (!(mask & HCI_LM_ACCEPT)) + goto unlock; +- } + + if (!(flags & HCI_PROTO_DEFER)) + goto unlock; +@@ -6938,24 +6959,11 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data, + (hdev, + le16_to_cpu(ev->sync_handle)); + +- if (pa_sync) +- goto unlock; +- +- /* Add connection to indicate the PA sync event */ +- pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY, +- HCI_ROLE_SLAVE); +- + if (IS_ERR(pa_sync)) + goto unlock; + +- pa_sync->sync_handle = le16_to_cpu(ev->sync_handle); +- set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags); +- + /* Notify iso layer */ +- hci_connect_cfm(pa_sync, 0x00); +- +- /* Notify MGMT layer */ +- mgmt_device_connected(hdev, pa_sync, NULL, 0); ++ hci_connect_cfm(pa_sync, 0); + + unlock: + hci_dev_unlock(hdev); +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 6cb41f9d174e2..00c0d8413c638 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -54,7 +54,6 @@ static void iso_sock_kill(struct sock *sk); + enum { + BT_SK_BIG_SYNC, + BT_SK_PA_SYNC, +- BT_SK_PA_SYNC_TERM, + }; + + struct iso_pinfo { +@@ -81,6 +80,7 @@ static bool check_ucast_qos(struct bt_iso_qos *qos); + static bool check_bcast_qos(struct bt_iso_qos *qos); + static bool iso_match_sid(struct sock *sk, void *data); + static bool iso_match_sync_handle(struct sock *sk, void *data); ++static bool iso_match_sync_handle_pa_report(struct sock *sk, void *data); + static void iso_sock_disconn(struct sock *sk); + + typedef bool (*iso_sock_match_t)(struct sock *sk, void *data); +@@ -197,21 +197,10 @@ static void iso_chan_del(struct sock *sk, int err) + sock_set_flag(sk, SOCK_ZAPPED); + } + +-static bool iso_match_conn_sync_handle(struct sock *sk, void *data) +-{ +- struct hci_conn *hcon = data; +- +- if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) +- return false; +- +- return hcon->sync_handle == iso_pi(sk)->sync_handle; +-} +- + static void iso_conn_del(struct hci_conn *hcon, int err) + { + struct iso_conn *conn = hcon->iso_data; + struct sock *sk; +- struct sock *parent; + + if (!conn) + return; +@@ -227,26 +216,6 @@ static void iso_conn_del(struct hci_conn *hcon, int err) + + if (sk) { + lock_sock(sk); +- +- /* While a PA sync hcon is in the process of closing, +- * mark parent socket with a flag, so that any residual +- * BIGInfo adv reports that arrive before PA sync is +- * terminated are not processed anymore. +- */ +- if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) { +- parent = iso_get_sock(&hcon->src, +- &hcon->dst, +- BT_LISTEN, +- iso_match_conn_sync_handle, +- hcon); +- +- if (parent) { +- set_bit(BT_SK_PA_SYNC_TERM, +- &iso_pi(parent)->flags); +- sock_put(parent); +- } +- } +- + iso_sock_clear_timer(sk); + iso_chan_del(sk, err); + release_sock(sk); +@@ -860,6 +829,7 @@ static struct sock *iso_sock_alloc(struct net *net, struct socket *sock, + iso_pi(sk)->src_type = BDADDR_LE_PUBLIC; + + iso_pi(sk)->qos = default_qos; ++ iso_pi(sk)->sync_handle = -1; + + bt_sock_link(&iso_sk_list, sk); + return sk; +@@ -907,7 +877,6 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr, + return -EINVAL; + + iso_pi(sk)->dst_type = sa->iso_bc->bc_bdaddr_type; +- iso_pi(sk)->sync_handle = -1; + + if (sa->iso_bc->bc_sid > 0x0f) + return -EINVAL; +@@ -984,7 +953,8 @@ static int iso_sock_bind(struct socket *sock, struct sockaddr *addr, + /* Allow the user to bind a PA sync socket to a number + * of BISes to sync to. + */ +- if (sk->sk_state == BT_CONNECT2 && ++ if ((sk->sk_state == BT_CONNECT2 || ++ sk->sk_state == BT_CONNECTED) && + test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) { + err = iso_sock_bind_pa_sk(sk, sa, addr_len); + goto done; +@@ -1396,6 +1366,16 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg, + } + release_sock(sk); + return 0; ++ case BT_CONNECTED: ++ if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) { ++ iso_conn_big_sync(sk); ++ sk->sk_state = BT_LISTEN; ++ release_sock(sk); ++ return 0; ++ } ++ ++ release_sock(sk); ++ break; + case BT_CONNECT: + release_sock(sk); + return iso_connect_cis(sk); +@@ -1541,7 +1521,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, + + case BT_ISO_QOS: + if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND && +- sk->sk_state != BT_CONNECT2) { ++ sk->sk_state != BT_CONNECT2 && ++ (!test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags) || ++ sk->sk_state != BT_CONNECTED)) { + err = -EINVAL; + break; + } +@@ -1762,7 +1744,7 @@ static void iso_conn_ready(struct iso_conn *conn) + struct sock *sk = conn->sk; + struct hci_ev_le_big_sync_estabilished *ev = NULL; + struct hci_ev_le_pa_sync_established *ev2 = NULL; +- struct hci_evt_le_big_info_adv_report *ev3 = NULL; ++ struct hci_ev_le_per_adv_report *ev3 = NULL; + struct hci_conn *hcon; + + BT_DBG("conn %p", conn); +@@ -1799,12 +1781,12 @@ static void iso_conn_ready(struct iso_conn *conn) + iso_match_sid, ev2); + } else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) { + ev3 = hci_recv_event_data(hcon->hdev, +- HCI_EVT_LE_BIG_INFO_ADV_REPORT); ++ HCI_EV_LE_PER_ADV_REPORT); + if (ev3) + parent = iso_get_sock(&hcon->src, + &hcon->dst, + BT_LISTEN, +- iso_match_sync_handle, ++ iso_match_sync_handle_pa_report, + ev3); + } + +@@ -1847,7 +1829,6 @@ static void iso_conn_ready(struct iso_conn *conn) + + if (ev3) { + iso_pi(sk)->qos = iso_pi(parent)->qos; +- iso_pi(sk)->qos.bcast.encryption = ev3->encryption; + hcon->iso_qos = iso_pi(sk)->qos; + iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis; + memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS); +@@ -1941,26 +1922,29 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + + ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT); + if (ev2) { +- /* Try to get PA sync listening socket, if it exists */ +- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN, +- iso_match_pa_sync_flag, NULL); +- +- if (!sk) { +- sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN, +- iso_match_sync_handle, ev2); +- +- /* If PA Sync is in process of terminating, +- * do not handle any more BIGInfo adv reports. +- */ +- +- if (sk && test_bit(BT_SK_PA_SYNC_TERM, +- &iso_pi(sk)->flags)) +- return 0; ++ /* Check if BIGInfo report has already been handled */ ++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECTED, ++ iso_match_sync_handle, ev2); ++ if (sk) { ++ sock_put(sk); ++ sk = NULL; ++ goto done; + } + ++ /* Try to get PA sync socket, if it exists */ ++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_CONNECT2, ++ iso_match_sync_handle, ev2); ++ if (!sk) ++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, ++ BT_LISTEN, ++ iso_match_sync_handle, ++ ev2); ++ + if (sk) { + int err; + ++ iso_pi(sk)->qos.bcast.encryption = ev2->encryption; ++ + if (ev2->num_bis < iso_pi(sk)->bc_num_bis) + iso_pi(sk)->bc_num_bis = ev2->num_bis; + +@@ -1979,6 +1963,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + } + } + } ++ ++ goto done; + } + + ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT); +diff --git a/net/core/dst_cache.c b/net/core/dst_cache.c +index 0ccfd5fa5cb9b..0c0bdb058c5b1 100644 +--- a/net/core/dst_cache.c ++++ b/net/core/dst_cache.c +@@ -83,7 +83,7 @@ struct rtable *dst_cache_get_ip4(struct dst_cache *dst_cache, __be32 *saddr) + return NULL; + + *saddr = idst->in_saddr.s_addr; +- return container_of(dst, struct rtable, dst); ++ return dst_rtable(dst); + } + EXPORT_SYMBOL_GPL(dst_cache_get_ip4); + +@@ -112,7 +112,7 @@ void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst, + + idst = this_cpu_ptr(dst_cache->cache); + dst_cache_per_cpu_dst_set(this_cpu_ptr(dst_cache->cache), dst, +- rt6_get_cookie((struct rt6_info *)dst)); ++ rt6_get_cookie(dst_rt6_info(dst))); + idst->in6_saddr = *saddr; + } + EXPORT_SYMBOL_GPL(dst_cache_set_ip6); +diff --git a/net/core/filter.c b/net/core/filter.c +index ae5254f712c94..a5856a8b4498b 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2215,7 +2215,7 @@ static int bpf_out_neigh_v6(struct net *net, struct sk_buff *skb, + rcu_read_lock(); + if (!nh) { + dst = skb_dst(skb); +- nexthop = rt6_nexthop(container_of(dst, struct rt6_info, dst), ++ nexthop = rt6_nexthop(dst_rt6_info(dst), + &ipv6_hdr(skb)->daddr); + } else { + nexthop = &nh->ipv6_nh; +@@ -2314,8 +2314,7 @@ static int bpf_out_neigh_v4(struct net *net, struct sk_buff *skb, + + rcu_read_lock(); + if (!nh) { +- struct dst_entry *dst = skb_dst(skb); +- struct rtable *rt = container_of(dst, struct rtable, dst); ++ struct rtable *rt = skb_rtable(skb); + + neigh = ip_neigh_for_gw(rt, skb, &is_v6gw); + } else if (nh->nh_family == AF_INET6) { +diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c +index 049c3adeb8504..4e3651101b866 100644 +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -161,9 +161,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) + skb->dev = dev; + skb_reset_mac_header(skb); + +- eth = (struct ethhdr *)skb->data; +- skb_pull_inline(skb, ETH_HLEN); +- ++ eth = eth_skb_pull_mac(skb); + eth_skb_pkt_type(skb, dev); + + /* +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index fafb123f798be..5622ddd3bf55b 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -758,7 +758,9 @@ void __inet_accept(struct socket *sock, struct socket *newsock, struct sock *new + sock_rps_record_flow(newsk); + WARN_ON(!((1 << newsk->sk_state) & + (TCPF_ESTABLISHED | TCPF_SYN_RECV | +- TCPF_CLOSE_WAIT | TCPF_CLOSE))); ++ TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | ++ TCPF_CLOSING | TCPF_CLOSE_WAIT | ++ TCPF_CLOSE))); + + if (test_bit(SOCK_SUPPORT_ZC, &sock->flags)) + set_bit(SOCK_SUPPORT_ZC, &newsock->flags); +@@ -1306,8 +1308,8 @@ static int inet_sk_reselect_saddr(struct sock *sk) + + int inet_sk_rebuild_header(struct sock *sk) + { ++ struct rtable *rt = dst_rtable(__sk_dst_check(sk, 0)); + struct inet_sock *inet = inet_sk(sk); +- struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); + __be32 daddr; + struct ip_options_rcu *inet_opt; + struct flowi4 *fl4; +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index 7e45c34c8340a..8382cc998bff8 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -1882,10 +1882,11 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) + goto done; + + if (fillargs.ifindex) { +- err = -ENODEV; + dev = dev_get_by_index_rcu(tgt_net, fillargs.ifindex); +- if (!dev) ++ if (!dev) { ++ err = -ENODEV; + goto done; ++ } + in_dev = __in_dev_get_rcu(dev); + if (!in_dev) + goto done; +@@ -1897,7 +1898,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) + + cb->seq = inet_base_seq(tgt_net); + +- for_each_netdev_dump(net, dev, ctx->ifindex) { ++ for_each_netdev_dump(tgt_net, dev, ctx->ifindex) { + in_dev = __in_dev_get_rcu(dev); + if (!in_dev) + continue; +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index 437e782b9663b..207482d30dc7e 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -483,6 +483,7 @@ static struct rtable *icmp_route_lookup(struct net *net, + struct icmp_bxm *param) + { + struct net_device *route_lookup_dev; ++ struct dst_entry *dst, *dst2; + struct rtable *rt, *rt2; + struct flowi4 fl4_dec; + int err; +@@ -508,16 +509,17 @@ static struct rtable *icmp_route_lookup(struct net *net, + /* No need to clone since we're just using its address. */ + rt2 = rt; + +- rt = (struct rtable *) xfrm_lookup(net, &rt->dst, +- flowi4_to_flowi(fl4), NULL, 0); +- if (!IS_ERR(rt)) { ++ dst = xfrm_lookup(net, &rt->dst, ++ flowi4_to_flowi(fl4), NULL, 0); ++ rt = dst_rtable(dst); ++ if (!IS_ERR(dst)) { + if (rt != rt2) + return rt; +- } else if (PTR_ERR(rt) == -EPERM) { ++ } else if (PTR_ERR(dst) == -EPERM) { + rt = NULL; +- } else ++ } else { + return rt; +- ++ } + err = xfrm_decode_session_reverse(net, skb_in, flowi4_to_flowi(&fl4_dec), AF_INET); + if (err) + goto relookup_failed; +@@ -551,19 +553,19 @@ static struct rtable *icmp_route_lookup(struct net *net, + if (err) + goto relookup_failed; + +- rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst, +- flowi4_to_flowi(&fl4_dec), NULL, +- XFRM_LOOKUP_ICMP); +- if (!IS_ERR(rt2)) { ++ dst2 = xfrm_lookup(net, &rt2->dst, flowi4_to_flowi(&fl4_dec), NULL, ++ XFRM_LOOKUP_ICMP); ++ rt2 = dst_rtable(dst2); ++ if (!IS_ERR(dst2)) { + dst_release(&rt->dst); + memcpy(fl4, &fl4_dec, sizeof(*fl4)); + rt = rt2; +- } else if (PTR_ERR(rt2) == -EPERM) { ++ } else if (PTR_ERR(dst2) == -EPERM) { + if (rt) + dst_release(&rt->dst); + return rt2; + } else { +- err = PTR_ERR(rt2); ++ err = PTR_ERR(dst2); + goto relookup_failed; + } + return rt; +diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c +index 5e9c8156656a7..d6fbcbd2358a5 100644 +--- a/net/ipv4/ip_input.c ++++ b/net/ipv4/ip_input.c +@@ -616,7 +616,7 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk, + dst = skb_dst(skb); + if (curr_dst != dst) { + hint = ip_extract_route_hint(net, skb, +- ((struct rtable *)dst)->rt_type); ++ dst_rtable(dst)->rt_type); + + /* dispatch old sublist */ + if (!list_empty(&sublist)) +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 39229fd0601a1..9500031a1f55b 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -198,7 +198,7 @@ EXPORT_SYMBOL_GPL(ip_build_and_send_pkt); + static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb) + { + struct dst_entry *dst = skb_dst(skb); +- struct rtable *rt = (struct rtable *)dst; ++ struct rtable *rt = dst_rtable(dst); + struct net_device *dev = dst->dev; + unsigned int hh_len = LL_RESERVED_SPACE(dev); + struct neighbour *neigh; +@@ -475,7 +475,7 @@ int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, + goto packet_routed; + + /* Make sure we can route this packet. */ +- rt = (struct rtable *)__sk_dst_check(sk, 0); ++ rt = dst_rtable(__sk_dst_check(sk, 0)); + if (!rt) { + __be32 daddr; + +@@ -971,7 +971,7 @@ static int __ip_append_data(struct sock *sk, + bool zc = false; + unsigned int maxfraglen, fragheaderlen, maxnonfragsize; + int csummode = CHECKSUM_NONE; +- struct rtable *rt = (struct rtable *)cork->dst; ++ struct rtable *rt = dst_rtable(cork->dst); + bool paged, hold_tskey, extra_uref = false; + unsigned int wmem_alloc_delta = 0; + u32 tskey = 0; +@@ -1390,7 +1390,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, + struct inet_sock *inet = inet_sk(sk); + struct net *net = sock_net(sk); + struct ip_options *opt = NULL; +- struct rtable *rt = (struct rtable *)cork->dst; ++ struct rtable *rt = dst_rtable(cork->dst); + struct iphdr *iph; + u8 pmtudisc, ttl; + __be16 df = 0; +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 1b8d8ff9a2375..0e4bd528428e9 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -543,7 +543,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, + struct rt6_info *rt6; + __be32 daddr; + +- rt6 = skb_valid_dst(skb) ? (struct rt6_info *)skb_dst(skb) : ++ rt6 = skb_valid_dst(skb) ? dst_rt6_info(skb_dst(skb)) : + NULL; + daddr = md ? dst : tunnel->parms.iph.daddr; + +diff --git a/net/ipv4/netfilter/nf_tproxy_ipv4.c b/net/ipv4/netfilter/nf_tproxy_ipv4.c +index 69e3317996043..73e66a088e25e 100644 +--- a/net/ipv4/netfilter/nf_tproxy_ipv4.c ++++ b/net/ipv4/netfilter/nf_tproxy_ipv4.c +@@ -58,6 +58,8 @@ __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) + + laddr = 0; + indev = __in_dev_get_rcu(skb->dev); ++ if (!indev) ++ return daddr; + + in_dev_for_each_ifa_rcu(ifa, indev) { + if (ifa->ifa_flags & IFA_F_SECONDARY) +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index b814fdab19f71..3fcf084fbda5d 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -132,7 +132,8 @@ struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); + static unsigned int ipv4_default_advmss(const struct dst_entry *dst); + INDIRECT_CALLABLE_SCOPE + unsigned int ipv4_mtu(const struct dst_entry *dst); +-static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); ++static void ipv4_negative_advice(struct sock *sk, ++ struct dst_entry *dst); + static void ipv4_link_failure(struct sk_buff *skb); + static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb, u32 mtu, +@@ -831,28 +832,21 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf + u32 mark = skb->mark; + __u8 tos = iph->tos; + +- rt = (struct rtable *) dst; ++ rt = dst_rtable(dst); + + __build_flow_key(net, &fl4, sk, iph, oif, tos, prot, mark, 0); + __ip_do_redirect(rt, skb, &fl4, true); + } + +-static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) ++static void ipv4_negative_advice(struct sock *sk, ++ struct dst_entry *dst) + { +- struct rtable *rt = (struct rtable *)dst; +- struct dst_entry *ret = dst; ++ struct rtable *rt = dst_rtable(dst); + +- if (rt) { +- if (dst->obsolete > 0) { +- ip_rt_put(rt); +- ret = NULL; +- } else if ((rt->rt_flags & RTCF_REDIRECTED) || +- rt->dst.expires) { +- ip_rt_put(rt); +- ret = NULL; +- } +- } +- return ret; ++ if ((dst->obsolete > 0) || ++ (rt->rt_flags & RTCF_REDIRECTED) || ++ rt->dst.expires) ++ sk_dst_reset(sk); + } + + /* +@@ -1056,7 +1050,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb, u32 mtu, + bool confirm_neigh) + { +- struct rtable *rt = (struct rtable *) dst; ++ struct rtable *rt = dst_rtable(dst); + struct flowi4 fl4; + + ip_rt_build_flow_key(&fl4, sk, skb); +@@ -1127,7 +1121,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) + + __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0); + +- rt = (struct rtable *)odst; ++ rt = dst_rtable(odst); + if (odst->obsolete && !odst->ops->check(odst, 0)) { + rt = ip_route_output_flow(sock_net(sk), &fl4, sk); + if (IS_ERR(rt)) +@@ -1136,7 +1130,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) + new = true; + } + +- __ip_rt_update_pmtu((struct rtable *)xfrm_dst_path(&rt->dst), &fl4, mtu); ++ __ip_rt_update_pmtu(dst_rtable(xfrm_dst_path(&rt->dst)), &fl4, mtu); + + if (!dst_check(&rt->dst, 0)) { + if (new) +@@ -1193,7 +1187,7 @@ EXPORT_SYMBOL_GPL(ipv4_sk_redirect); + INDIRECT_CALLABLE_SCOPE struct dst_entry *ipv4_dst_check(struct dst_entry *dst, + u32 cookie) + { +- struct rtable *rt = (struct rtable *) dst; ++ struct rtable *rt = dst_rtable(dst); + + /* All IPV4 dsts are created with ->obsolete set to the value + * DST_OBSOLETE_FORCE_CHK which forces validation calls down +@@ -1528,10 +1522,8 @@ void rt_del_uncached_list(struct rtable *rt) + + static void ipv4_dst_destroy(struct dst_entry *dst) + { +- struct rtable *rt = (struct rtable *)dst; +- + ip_dst_metrics_put(dst); +- rt_del_uncached_list(rt); ++ rt_del_uncached_list(dst_rtable(dst)); + } + + void rt_flush_dev(struct net_device *dev) +@@ -2832,7 +2824,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { + + struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) + { +- struct rtable *ort = (struct rtable *) dst_orig; ++ struct rtable *ort = dst_rtable(dst_orig); + struct rtable *rt; + + rt = dst_alloc(&ipv4_dst_blackhole_ops, NULL, DST_OBSOLETE_DEAD, 0); +@@ -2877,9 +2869,9 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, + + if (flp4->flowi4_proto) { + flp4->flowi4_oif = rt->dst.dev->ifindex; +- rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst, +- flowi4_to_flowi(flp4), +- sk, 0); ++ rt = dst_rtable(xfrm_lookup_route(net, &rt->dst, ++ flowi4_to_flowi(flp4), ++ sk, 0)); + } + + return rt; +diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c +index e33fbe4933e42..b004280855f87 100644 +--- a/net/ipv4/tcp_dctcp.c ++++ b/net/ipv4/tcp_dctcp.c +@@ -58,7 +58,18 @@ struct dctcp { + }; + + static unsigned int dctcp_shift_g __read_mostly = 4; /* g = 1/2^4 */ +-module_param(dctcp_shift_g, uint, 0644); ++ ++static int dctcp_shift_g_set(const char *val, const struct kernel_param *kp) ++{ ++ return param_set_uint_minmax(val, kp, 0, 10); ++} ++ ++static const struct kernel_param_ops dctcp_shift_g_ops = { ++ .set = dctcp_shift_g_set, ++ .get = param_get_uint, ++}; ++ ++module_param_cb(dctcp_shift_g, &dctcp_shift_g_ops, &dctcp_shift_g, 0644); + MODULE_PARM_DESC(dctcp_shift_g, "parameter g for updating dctcp_alpha"); + + static unsigned int dctcp_alpha_on_init __read_mostly = DCTCP_MAX_ALPHA; +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index b5ad0c527c521..72d3bf136810d 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1218,7 +1218,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + } + + if (connected) +- rt = (struct rtable *)sk_dst_check(sk, 0); ++ rt = dst_rtable(sk_dst_check(sk, 0)); + + if (!rt) { + struct net *net = sock_net(sk); +diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c +index c33bca2c38415..1853a8415d9f1 100644 +--- a/net/ipv4/xfrm4_policy.c ++++ b/net/ipv4/xfrm4_policy.c +@@ -69,7 +69,7 @@ static int xfrm4_get_saddr(struct net *net, int oif, + static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + const struct flowi *fl) + { +- struct rtable *rt = (struct rtable *)xdst->route; ++ struct rtable *rt = dst_rtable(xdst->route); + const struct flowi4 *fl4 = &fl->u.ip4; + + xdst->u.rt.rt_iif = fl4->flowi4_iif; +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index 1635da07285f2..d285c1f6f1a61 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -212,7 +212,7 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type, + } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { + res = true; + } else { +- struct rt6_info *rt = (struct rt6_info *)dst; ++ struct rt6_info *rt = dst_rt6_info(dst); + int tmo = net->ipv6.sysctl.icmpv6_time; + struct inet_peer *peer; + +@@ -241,7 +241,7 @@ static bool icmpv6_rt_has_prefsrc(struct sock *sk, u8 type, + + dst = ip6_route_output(net, sk, fl6); + if (!dst->error) { +- struct rt6_info *rt = (struct rt6_info *)dst; ++ struct rt6_info *rt = dst_rt6_info(dst); + struct in6_addr prefsrc; + + rt6_get_prefsrc(rt, &prefsrc); +@@ -616,7 +616,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + if (ip6_append_data(sk, icmpv6_getfrag, &msg, + len + sizeof(struct icmp6hdr), + sizeof(struct icmp6hdr), +- &ipc6, &fl6, (struct rt6_info *)dst, ++ &ipc6, &fl6, dst_rt6_info(dst), + MSG_DONTWAIT)) { + ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); +@@ -803,7 +803,7 @@ static enum skb_drop_reason icmpv6_echo_reply(struct sk_buff *skb) + if (ip6_append_data(sk, icmpv6_getfrag, &msg, + skb->len + sizeof(struct icmp6hdr), + sizeof(struct icmp6hdr), &ipc6, &fl6, +- (struct rt6_info *)dst, MSG_DONTWAIT)) { ++ dst_rt6_info(dst), MSG_DONTWAIT)) { + __ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); + } else { +diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c +index 8c1ce78956bae..0601bad798221 100644 +--- a/net/ipv6/ila/ila_lwt.c ++++ b/net/ipv6/ila/ila_lwt.c +@@ -38,7 +38,7 @@ static inline struct ila_params *ila_params_lwtunnel( + static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) + { + struct dst_entry *orig_dst = skb_dst(skb); +- struct rt6_info *rt = (struct rt6_info *)orig_dst; ++ struct rt6_info *rt = dst_rt6_info(orig_dst); + struct ila_lwt *ilwt = ila_lwt_lwtunnel(orig_dst->lwtstate); + struct dst_entry *dst; + int err = -EINVAL; +@@ -70,7 +70,7 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_oif = orig_dst->dev->ifindex; + fl6.flowi6_iif = LOOPBACK_IFINDEX; +- fl6.daddr = *rt6_nexthop((struct rt6_info *)orig_dst, ++ fl6.daddr = *rt6_nexthop(dst_rt6_info(orig_dst), + &ip6h->daddr); + + dst = ip6_route_output(net, NULL, &fl6); +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 97b0788b31bae..27d8725445e35 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -120,7 +120,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); + + rcu_read_lock(); +- nexthop = rt6_nexthop((struct rt6_info *)dst, daddr); ++ nexthop = rt6_nexthop(dst_rt6_info(dst), daddr); + neigh = __ipv6_neigh_lookup_noref(dev, nexthop); + + if (unlikely(IS_ERR_OR_NULL(neigh))) { +@@ -599,7 +599,7 @@ int ip6_forward(struct sk_buff *skb) + * send a redirect. + */ + +- rt = (struct rt6_info *) dst; ++ rt = dst_rt6_info(dst); + if (rt->rt6i_flags & RTF_GATEWAY) + target = &rt->rt6i_gateway; + else +@@ -856,7 +856,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + int (*output)(struct net *, struct sock *, struct sk_buff *)) + { + struct sk_buff *frag; +- struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); ++ struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? + inet6_sk(skb->sk) : NULL; + bool mono_delivery_time = skb->mono_delivery_time; +@@ -1063,7 +1063,7 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, + return NULL; + } + +- rt = (struct rt6_info *)dst; ++ rt = dst_rt6_info(dst); + /* Yes, checking route validity in not connected + * case is not very simple. Take into account, + * that we do not support routing by source, TOS, +@@ -1118,7 +1118,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, + struct rt6_info *rt; + + *dst = ip6_route_output(net, sk, fl6); +- rt = (*dst)->error ? NULL : (struct rt6_info *)*dst; ++ rt = (*dst)->error ? NULL : dst_rt6_info(*dst); + + rcu_read_lock(); + from = rt ? rcu_dereference(rt->from) : NULL; +@@ -1159,7 +1159,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, + * dst entry and replace it instead with the + * dst entry of the nexthop router + */ +- rt = (struct rt6_info *) *dst; ++ rt = dst_rt6_info(*dst); + rcu_read_lock(); + n = __ipv6_neigh_lookup_noref(rt->dst.dev, + rt6_nexthop(rt, &fl6->daddr)); +@@ -1423,7 +1423,7 @@ static int __ip6_append_data(struct sock *sk, + int offset = 0; + bool zc = false; + u32 tskey = 0; +- struct rt6_info *rt = (struct rt6_info *)cork->dst; ++ struct rt6_info *rt = dst_rt6_info(cork->dst); + bool paged, hold_tskey, extra_uref = false; + struct ipv6_txoptions *opt = v6_cork->opt; + int csummode = CHECKSUM_NONE; +@@ -1877,7 +1877,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, + struct net *net = sock_net(sk); + struct ipv6hdr *hdr; + struct ipv6_txoptions *opt = v6_cork->opt; +- struct rt6_info *rt = (struct rt6_info *)cork->base.dst; ++ struct rt6_info *rt = dst_rt6_info(cork->base.dst); + struct flowi6 *fl6 = &cork->fl.u.ip6; + unsigned char proto = fl6->flowi6_proto; + +@@ -1949,7 +1949,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, + int ip6_send_skb(struct sk_buff *skb) + { + struct net *net = sock_net(skb->sk); +- struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); ++ struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + int err; + + err = ip6_local_out(net, skb->sk, skb); +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index cb0ee81a068a4..dd342e6ecf3f4 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -2273,7 +2273,7 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, + int err; + struct mr_table *mrt; + struct mfc6_cache *cache; +- struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); ++ struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + + mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); + if (!mrt) +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index ae134634c323c..d914b23256ce6 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -1722,7 +1722,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) + if (IS_ERR(dst)) + return; + +- rt = (struct rt6_info *) dst; ++ rt = dst_rt6_info(dst); + + if (rt->rt6i_flags & RTF_GATEWAY) { + ND_PRINTK(2, warn, +diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c +index ef2059c889554..88b3fcacd4f94 100644 +--- a/net/ipv6/ping.c ++++ b/net/ipv6/ping.c +@@ -154,7 +154,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, false); + if (IS_ERR(dst)) + return PTR_ERR(dst); +- rt = (struct rt6_info *) dst; ++ rt = dst_rt6_info(dst); + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = READ_ONCE(np->mcast_oif); +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 0d896ca7b5891..2eedf255600b9 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -598,7 +598,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, + struct ipv6hdr *iph; + struct sk_buff *skb; + int err; +- struct rt6_info *rt = (struct rt6_info *)*dstp; ++ struct rt6_info *rt = dst_rt6_info(*dstp); + int hlen = LL_RESERVED_SPACE(rt->dst.dev); + int tlen = rt->dst.dev->needed_tailroom; + +@@ -917,7 +917,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + ipc6.opt = opt; + lock_sock(sk); + err = ip6_append_data(sk, raw6_getfrag, &rfv, +- len, 0, &ipc6, &fl6, (struct rt6_info *)dst, ++ len, 0, &ipc6, &fl6, dst_rt6_info(dst), + msg->msg_flags); + + if (err) +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 1f4b935a0e57a..8d5257c3f0842 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -87,7 +87,8 @@ struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); + static unsigned int ip6_default_advmss(const struct dst_entry *dst); + INDIRECT_CALLABLE_SCOPE + unsigned int ip6_mtu(const struct dst_entry *dst); +-static struct dst_entry *ip6_negative_advice(struct dst_entry *); ++static void ip6_negative_advice(struct sock *sk, ++ struct dst_entry *dst); + static void ip6_dst_destroy(struct dst_entry *); + static void ip6_dst_ifdown(struct dst_entry *, + struct net_device *dev); +@@ -226,7 +227,7 @@ static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst, + struct sk_buff *skb, + const void *daddr) + { +- const struct rt6_info *rt = container_of(dst, struct rt6_info, dst); ++ const struct rt6_info *rt = dst_rt6_info(dst); + + return ip6_neigh_lookup(rt6_nexthop(rt, &in6addr_any), + dst->dev, skb, daddr); +@@ -234,8 +235,8 @@ static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst, + + static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr) + { ++ const struct rt6_info *rt = dst_rt6_info(dst); + struct net_device *dev = dst->dev; +- struct rt6_info *rt = (struct rt6_info *)dst; + + daddr = choose_neigh_daddr(rt6_nexthop(rt, &in6addr_any), NULL, daddr); + if (!daddr) +@@ -354,7 +355,7 @@ EXPORT_SYMBOL(ip6_dst_alloc); + + static void ip6_dst_destroy(struct dst_entry *dst) + { +- struct rt6_info *rt = (struct rt6_info *)dst; ++ struct rt6_info *rt = dst_rt6_info(dst); + struct fib6_info *from; + struct inet6_dev *idev; + +@@ -373,7 +374,7 @@ static void ip6_dst_destroy(struct dst_entry *dst) + + static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev) + { +- struct rt6_info *rt = (struct rt6_info *)dst; ++ struct rt6_info *rt = dst_rt6_info(dst); + struct inet6_dev *idev = rt->rt6i_idev; + + if (idev && idev->dev != blackhole_netdev) { +@@ -1288,7 +1289,7 @@ struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, + + dst = fib6_rule_lookup(net, &fl6, skb, flags, ip6_pol_route_lookup); + if (dst->error == 0) +- return (struct rt6_info *) dst; ++ return dst_rt6_info(dst); + + dst_release(dst); + +@@ -2647,7 +2648,7 @@ struct dst_entry *ip6_route_output_flags(struct net *net, + + rcu_read_lock(); + dst = ip6_route_output_flags_noref(net, sk, fl6, flags); +- rt6 = (struct rt6_info *)dst; ++ rt6 = dst_rt6_info(dst); + /* For dst cached in uncached_list, refcnt is already taken. */ + if (list_empty(&rt6->dst.rt_uncached) && !dst_hold_safe(dst)) { + dst = &net->ipv6.ip6_null_entry->dst; +@@ -2661,7 +2662,7 @@ EXPORT_SYMBOL_GPL(ip6_route_output_flags); + + struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) + { +- struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig; ++ struct rt6_info *rt, *ort = dst_rt6_info(dst_orig); + struct net_device *loopback_dev = net->loopback_dev; + struct dst_entry *new = NULL; + +@@ -2744,7 +2745,7 @@ INDIRECT_CALLABLE_SCOPE struct dst_entry *ip6_dst_check(struct dst_entry *dst, + struct fib6_info *from; + struct rt6_info *rt; + +- rt = container_of(dst, struct rt6_info, dst); ++ rt = dst_rt6_info(dst); + + if (rt->sernum) + return rt6_is_valid(rt) ? dst : NULL; +@@ -2770,24 +2771,24 @@ INDIRECT_CALLABLE_SCOPE struct dst_entry *ip6_dst_check(struct dst_entry *dst, + } + EXPORT_INDIRECT_CALLABLE(ip6_dst_check); + +-static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) ++static void ip6_negative_advice(struct sock *sk, ++ struct dst_entry *dst) + { +- struct rt6_info *rt = (struct rt6_info *) dst; ++ struct rt6_info *rt = dst_rt6_info(dst); + +- if (rt) { +- if (rt->rt6i_flags & RTF_CACHE) { +- rcu_read_lock(); +- if (rt6_check_expired(rt)) { +- rt6_remove_exception_rt(rt); +- dst = NULL; +- } +- rcu_read_unlock(); +- } else { +- dst_release(dst); +- dst = NULL; ++ if (rt->rt6i_flags & RTF_CACHE) { ++ rcu_read_lock(); ++ if (rt6_check_expired(rt)) { ++ /* counteract the dst_release() in sk_dst_reset() */ ++ dst_hold(dst); ++ sk_dst_reset(sk); ++ ++ rt6_remove_exception_rt(rt); + } ++ rcu_read_unlock(); ++ return; + } +- return dst; ++ sk_dst_reset(sk); + } + + static void ip6_link_failure(struct sk_buff *skb) +@@ -2796,7 +2797,7 @@ static void ip6_link_failure(struct sk_buff *skb) + + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0); + +- rt = (struct rt6_info *) skb_dst(skb); ++ rt = dst_rt6_info(skb_dst(skb)); + if (rt) { + rcu_read_lock(); + if (rt->rt6i_flags & RTF_CACHE) { +@@ -2852,7 +2853,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, + bool confirm_neigh) + { + const struct in6_addr *daddr, *saddr; +- struct rt6_info *rt6 = (struct rt6_info *)dst; ++ struct rt6_info *rt6 = dst_rt6_info(dst); + + /* Note: do *NOT* check dst_metric_locked(dst, RTAX_MTU) + * IPv6 pmtu discovery isn't optional, so 'mtu lock' cannot disable it. +@@ -4174,7 +4175,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu + } + } + +- rt = (struct rt6_info *) dst; ++ rt = dst_rt6_info(dst); + if (rt->rt6i_flags & RTF_REJECT) { + net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n"); + return; +@@ -5608,7 +5609,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, + int iif, int type, u32 portid, u32 seq, + unsigned int flags) + { +- struct rt6_info *rt6 = (struct rt6_info *)dst; ++ struct rt6_info *rt6 = dst_rt6_info(dst); + struct rt6key *rt6_dst, *rt6_src; + u32 *pmetrics, table, rt6_flags; + unsigned char nh_flags = 0; +@@ -6111,7 +6112,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, + } + + +- rt = container_of(dst, struct rt6_info, dst); ++ rt = dst_rt6_info(dst); + if (rt->dst.error) { + err = rt->dst.error; + ip6_rt_put(rt); +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index 861e0366f549d..bbf5b84a70fca 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -356,6 +356,7 @@ static int seg6_hmac_init_algo(void) + struct crypto_shash *tfm; + struct shash_desc *shash; + int i, alg_count, cpu; ++ int ret = -ENOMEM; + + alg_count = ARRAY_SIZE(hmac_algos); + +@@ -366,12 +367,14 @@ static int seg6_hmac_init_algo(void) + algo = &hmac_algos[i]; + algo->tfms = alloc_percpu(struct crypto_shash *); + if (!algo->tfms) +- return -ENOMEM; ++ goto error_out; + + for_each_possible_cpu(cpu) { + tfm = crypto_alloc_shash(algo->name, 0, 0); +- if (IS_ERR(tfm)) +- return PTR_ERR(tfm); ++ if (IS_ERR(tfm)) { ++ ret = PTR_ERR(tfm); ++ goto error_out; ++ } + p_tfm = per_cpu_ptr(algo->tfms, cpu); + *p_tfm = tfm; + } +@@ -383,18 +386,22 @@ static int seg6_hmac_init_algo(void) + + algo->shashs = alloc_percpu(struct shash_desc *); + if (!algo->shashs) +- return -ENOMEM; ++ goto error_out; + + for_each_possible_cpu(cpu) { + shash = kzalloc_node(shsize, GFP_KERNEL, + cpu_to_node(cpu)); + if (!shash) +- return -ENOMEM; ++ goto error_out; + *per_cpu_ptr(algo->shashs, cpu) = shash; + } + } + + return 0; ++ ++error_out: ++ seg6_hmac_exit(); ++ return ret; + } + + int __init seg6_hmac_init(void) +@@ -412,22 +419,29 @@ int __net_init seg6_hmac_net_init(struct net *net) + void seg6_hmac_exit(void) + { + struct seg6_hmac_algo *algo = NULL; ++ struct crypto_shash *tfm; ++ struct shash_desc *shash; + int i, alg_count, cpu; + + alg_count = ARRAY_SIZE(hmac_algos); + for (i = 0; i < alg_count; i++) { + algo = &hmac_algos[i]; +- for_each_possible_cpu(cpu) { +- struct crypto_shash *tfm; +- struct shash_desc *shash; + +- shash = *per_cpu_ptr(algo->shashs, cpu); +- kfree(shash); +- tfm = *per_cpu_ptr(algo->tfms, cpu); +- crypto_free_shash(tfm); ++ if (algo->shashs) { ++ for_each_possible_cpu(cpu) { ++ shash = *per_cpu_ptr(algo->shashs, cpu); ++ kfree(shash); ++ } ++ free_percpu(algo->shashs); ++ } ++ ++ if (algo->tfms) { ++ for_each_possible_cpu(cpu) { ++ tfm = *per_cpu_ptr(algo->tfms, cpu); ++ crypto_free_shash(tfm); ++ } ++ free_percpu(algo->tfms); + } +- free_percpu(algo->tfms); +- free_percpu(algo->shashs); + } + } + EXPORT_SYMBOL(seg6_hmac_exit); +diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c +index 03b877ff45588..a75df2ec8db0d 100644 +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -459,10 +459,8 @@ static int seg6_input_core(struct net *net, struct sock *sk, + int err; + + err = seg6_do_srh(skb); +- if (unlikely(err)) { +- kfree_skb(skb); +- return err; +- } ++ if (unlikely(err)) ++ goto drop; + + slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); + +@@ -486,7 +484,7 @@ static int seg6_input_core(struct net *net, struct sock *sk, + + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); + if (unlikely(err)) +- return err; ++ goto drop; + + if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, +@@ -494,6 +492,9 @@ static int seg6_input_core(struct net *net, struct sock *sk, + skb_dst(skb)->dev, seg6_input_finish); + + return seg6_input_finish(dev_net(skb->dev), NULL, skb); ++drop: ++ kfree_skb(skb); ++ return err; + } + + static int seg6_input_nf(struct sk_buff *skb) +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 3f4cba49e9ee6..5873b3c3562ed 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -95,11 +95,9 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) + struct dst_entry *dst = skb_dst(skb); + + if (dst && dst_hold_safe(dst)) { +- const struct rt6_info *rt = (const struct rt6_info *)dst; +- + rcu_assign_pointer(sk->sk_rx_dst, dst); + sk->sk_rx_dst_ifindex = skb->skb_iif; +- sk->sk_rx_dst_cookie = rt6_get_cookie(rt); ++ sk->sk_rx_dst_cookie = rt6_get_cookie(dst_rt6_info(dst)); + } + } + +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index e0dd5bc2b30eb..acafa0cdf74a8 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -910,11 +910,8 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, + + static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) + { +- if (udp_sk_rx_dst_set(sk, dst)) { +- const struct rt6_info *rt = (const struct rt6_info *)dst; +- +- sk->sk_rx_dst_cookie = rt6_get_cookie(rt); +- } ++ if (udp_sk_rx_dst_set(sk, dst)) ++ sk->sk_rx_dst_cookie = rt6_get_cookie(dst_rt6_info(dst)); + } + + /* wrapper for udp_queue_rcv_skb tacking care of csum conversion and +@@ -1585,7 +1582,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + + skb = ip6_make_skb(sk, getfrag, msg, ulen, + sizeof(struct udphdr), &ipc6, +- (struct rt6_info *)dst, ++ dst_rt6_info(dst), + msg->msg_flags, &cork); + err = PTR_ERR(skb); + if (!IS_ERR_OR_NULL(skb)) +@@ -1612,7 +1609,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + ipc6.dontfrag = inet6_test_bit(DONTFRAG, sk); + up->len += ulen; + err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr), +- &ipc6, fl6, (struct rt6_info *)dst, ++ &ipc6, fl6, dst_rt6_info(dst), + corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); + if (err) + udp_v6_flush_pending_frames(sk); +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 42fb6996b0777..ce48173c60e56 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -70,7 +70,7 @@ static int xfrm6_get_saddr(struct net *net, int oif, + static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, + const struct flowi *fl) + { +- struct rt6_info *rt = (struct rt6_info *)xdst->route; ++ struct rt6_info *rt = dst_rt6_info(xdst->route); + + xdst->u.dst.dev = dev; + netdev_hold(dev, &xdst->u.dst.dev_tracker, GFP_ATOMIC); +diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c +index 970af3983d116..19c8cc5289d59 100644 +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -459,7 +459,7 @@ static int l2tp_ip_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + + fl4 = &inet->cork.fl.u.ip4; + if (connected) +- rt = (struct rtable *)__sk_dst_check(sk, 0); ++ rt = dst_rtable(__sk_dst_check(sk, 0)); + + rcu_read_lock(); + if (!rt) { +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index 7bf14cf9ffaa9..8780ec64f3769 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -630,7 +630,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + ulen = len + (skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0); + err = ip6_append_data(sk, ip_generic_getfrag, msg, + ulen, transhdrlen, &ipc6, +- &fl6, (struct rt6_info *)dst, ++ &fl6, dst_rt6_info(dst), + msg->msg_flags); + if (err) + ip6_flush_pending_frames(sk); +diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c +index 8fc790f2a01bb..4385fd3b13be3 100644 +--- a/net/mpls/mpls_iptunnel.c ++++ b/net/mpls/mpls_iptunnel.c +@@ -81,7 +81,7 @@ static int mpls_xmit(struct sk_buff *skb) + ttl = net->mpls.default_ttl; + else + ttl = ip_hdr(skb)->ttl; +- rt = (struct rtable *)dst; ++ rt = dst_rtable(dst); + } else if (dst->ops->family == AF_INET6) { + if (tun_encap_info->ttl_propagate == MPLS_TTL_PROP_DISABLED) + ttl = tun_encap_info->default_ttl; +@@ -90,7 +90,7 @@ static int mpls_xmit(struct sk_buff *skb) + ttl = net->mpls.default_ttl; + else + ttl = ipv6_hdr(skb)->hop_limit; +- rt6 = (struct rt6_info *)dst; ++ rt6 = dst_rt6_info(dst); + } else { + goto drop; + } +diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c +index 6c3f28bc59b32..54e2a1dd7f5f5 100644 +--- a/net/netfilter/ipset/ip_set_list_set.c ++++ b/net/netfilter/ipset/ip_set_list_set.c +@@ -549,6 +549,9 @@ list_set_cancel_gc(struct ip_set *set) + + if (SET_WITH_TIMEOUT(set)) + timer_shutdown_sync(&map->gc); ++ ++ /* Flush list to drop references to other ipsets */ ++ list_set_flush(set); + } + + static const struct ip_set_type_variant set_variant = { +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index 65e0259178da4..e1f17392f58c1 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -180,7 +180,7 @@ static inline bool crosses_local_route_boundary(int skb_af, struct sk_buff *skb, + (!skb->dev || skb->dev->flags & IFF_LOOPBACK) && + (addr_type & IPV6_ADDR_LOOPBACK); + old_rt_is_local = __ip_vs_is_local_route6( +- (struct rt6_info *)skb_dst(skb)); ++ dst_rt6_info(skb_dst(skb))); + } else + #endif + { +@@ -318,7 +318,7 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + if (dest) { + dest_dst = __ip_vs_dst_check(dest); + if (likely(dest_dst)) +- rt = (struct rtable *) dest_dst->dst_cache; ++ rt = dst_rtable(dest_dst->dst_cache); + else { + dest_dst = ip_vs_dest_dst_alloc(); + spin_lock_bh(&dest->dst_lock); +@@ -481,7 +481,7 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + if (dest) { + dest_dst = __ip_vs_dst_check(dest); + if (likely(dest_dst)) +- rt = (struct rt6_info *) dest_dst->dst_cache; ++ rt = dst_rt6_info(dest_dst->dst_cache); + else { + u32 cookie; + +@@ -501,7 +501,7 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + ip_vs_dest_dst_free(dest_dst); + goto err_unreach; + } +- rt = (struct rt6_info *) dst; ++ rt = dst_rt6_info(dst); + cookie = rt6_get_cookie(rt); + __ip_vs_dst_set(dest, dest_dst, &rt->dst, cookie); + spin_unlock_bh(&dest->dst_lock); +@@ -517,7 +517,7 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, + rt_mode); + if (!dst) + goto err_unreach; +- rt = (struct rt6_info *) dst; ++ rt = dst_rt6_info(dst); + } + + local = __ip_vs_is_local_route6(rt); +@@ -862,7 +862,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + IP_VS_RT_MODE_RDR); + if (local < 0) + goto tx_error; +- rt = (struct rt6_info *) skb_dst(skb); ++ rt = dst_rt6_info(skb_dst(skb)); + /* + * Avoid duplicate tuple in reply direction for NAT traffic + * to local address when connection is sync-ed +@@ -1288,7 +1288,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + if (local) + return ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 1); + +- rt = (struct rt6_info *) skb_dst(skb); ++ rt = dst_rt6_info(skb_dst(skb)); + tdev = rt->dst.dev; + + /* +@@ -1590,7 +1590,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + &cp->daddr.in6, NULL, ipvsh, 0, rt_mode); + if (local < 0) + goto tx_error; +- rt = (struct rt6_info *) skb_dst(skb); ++ rt = dst_rt6_info(skb_dst(skb)); + /* + * Avoid duplicate tuple in reply direction for NAT traffic + * to local address when connection is sync-ed +diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c +index a0571339239c4..5c1ff07eaee0b 100644 +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -77,12 +77,8 @@ EXPORT_SYMBOL_GPL(flow_offload_alloc); + + static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple) + { +- const struct rt6_info *rt; +- +- if (flow_tuple->l3proto == NFPROTO_IPV6) { +- rt = (const struct rt6_info *)flow_tuple->dst_cache; +- return rt6_get_cookie(rt); +- } ++ if (flow_tuple->l3proto == NFPROTO_IPV6) ++ return rt6_get_cookie(dst_rt6_info(flow_tuple->dst_cache)); + + return 0; + } +diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c +index 5383bed3d3e00..c2c005234dcd3 100644 +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -434,7 +434,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, + return NF_ACCEPT; + + if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { +- rt = (struct rtable *)tuplehash->tuple.dst_cache; ++ rt = dst_rtable(tuplehash->tuple.dst_cache); + memset(skb->cb, 0, sizeof(struct inet_skb_parm)); + IPCB(skb)->iif = skb->dev->ifindex; + IPCB(skb)->flags = IPSKB_FORWARDED; +@@ -446,7 +446,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, + + switch (tuplehash->tuple.xmit_type) { + case FLOW_OFFLOAD_XMIT_NEIGH: +- rt = (struct rtable *)tuplehash->tuple.dst_cache; ++ rt = dst_rtable(tuplehash->tuple.dst_cache); + outdev = rt->dst.dev; + skb->dev = outdev; + nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +@@ -729,7 +729,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, + return NF_ACCEPT; + + if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { +- rt = (struct rt6_info *)tuplehash->tuple.dst_cache; ++ rt = dst_rt6_info(tuplehash->tuple.dst_cache); + memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); + IP6CB(skb)->iif = skb->dev->ifindex; + IP6CB(skb)->flags = IP6SKB_FORWARDED; +@@ -741,7 +741,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, + + switch (tuplehash->tuple.xmit_type) { + case FLOW_OFFLOAD_XMIT_NEIGH: +- rt = (struct rt6_info *)tuplehash->tuple.dst_cache; ++ rt = dst_rt6_info(tuplehash->tuple.dst_cache); + outdev = rt->dst.dev; + skb->dev = outdev; + nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); +diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c +index 00f4bd21c59b4..f1c31757e4969 100644 +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -169,7 +169,9 @@ instance_destroy_rcu(struct rcu_head *head) + struct nfqnl_instance *inst = container_of(head, struct nfqnl_instance, + rcu); + ++ rcu_read_lock(); + nfqnl_flush(inst, NULL, 0); ++ rcu_read_unlock(); + kfree(inst); + module_put(THIS_MODULE); + } +diff --git a/net/netfilter/nft_fib.c b/net/netfilter/nft_fib.c +index 37cfe6dd712d8..b58f62195ff3e 100644 +--- a/net/netfilter/nft_fib.c ++++ b/net/netfilter/nft_fib.c +@@ -35,11 +35,9 @@ int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr, + switch (priv->result) { + case NFT_FIB_RESULT_OIF: + case NFT_FIB_RESULT_OIFNAME: +- hooks = (1 << NF_INET_PRE_ROUTING); +- if (priv->flags & NFTA_FIB_F_IIF) { +- hooks |= (1 << NF_INET_LOCAL_IN) | +- (1 << NF_INET_FORWARD); +- } ++ hooks = (1 << NF_INET_PRE_ROUTING) | ++ (1 << NF_INET_LOCAL_IN) | ++ (1 << NF_INET_FORWARD); + break; + case NFT_FIB_RESULT_ADDRTYPE: + if (priv->flags & NFTA_FIB_F_IIF) +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index 0a689c8e0295d..0c43d748e23ae 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -45,36 +45,27 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len) + int mac_off = skb_mac_header(skb) - skb->data; + u8 *vlanh, *dst_u8 = (u8 *) d; + struct vlan_ethhdr veth; +- u8 vlan_hlen = 0; +- +- if ((skb->protocol == htons(ETH_P_8021AD) || +- skb->protocol == htons(ETH_P_8021Q)) && +- offset >= VLAN_ETH_HLEN && offset < VLAN_ETH_HLEN + VLAN_HLEN) +- vlan_hlen += VLAN_HLEN; + + vlanh = (u8 *) &veth; +- if (offset < VLAN_ETH_HLEN + vlan_hlen) { ++ if (offset < VLAN_ETH_HLEN) { + u8 ethlen = len; + +- if (vlan_hlen && +- skb_copy_bits(skb, mac_off, &veth, VLAN_ETH_HLEN) < 0) +- return false; +- else if (!nft_payload_rebuild_vlan_hdr(skb, mac_off, &veth)) ++ if (!nft_payload_rebuild_vlan_hdr(skb, mac_off, &veth)) + return false; + +- if (offset + len > VLAN_ETH_HLEN + vlan_hlen) +- ethlen -= offset + len - VLAN_ETH_HLEN - vlan_hlen; ++ if (offset + len > VLAN_ETH_HLEN) ++ ethlen -= offset + len - VLAN_ETH_HLEN; + +- memcpy(dst_u8, vlanh + offset - vlan_hlen, ethlen); ++ memcpy(dst_u8, vlanh + offset, ethlen); + + len -= ethlen; + if (len == 0) + return true; + + dst_u8 += ethlen; +- offset = ETH_HLEN + vlan_hlen; ++ offset = ETH_HLEN; + } else { +- offset -= VLAN_HLEN + vlan_hlen; ++ offset -= VLAN_HLEN; + } + + return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0; +@@ -154,12 +145,12 @@ int nft_payload_inner_offset(const struct nft_pktinfo *pkt) + return pkt->inneroff; + } + +-static bool nft_payload_need_vlan_copy(const struct nft_payload *priv) ++static bool nft_payload_need_vlan_adjust(u32 offset, u32 len) + { +- unsigned int len = priv->offset + priv->len; ++ unsigned int boundary = offset + len; + + /* data past ether src/dst requested, copy needed */ +- if (len > offsetof(struct ethhdr, h_proto)) ++ if (boundary > offsetof(struct ethhdr, h_proto)) + return true; + + return false; +@@ -183,7 +174,7 @@ void nft_payload_eval(const struct nft_expr *expr, + goto err; + + if (skb_vlan_tag_present(skb) && +- nft_payload_need_vlan_copy(priv)) { ++ nft_payload_need_vlan_adjust(priv->offset, priv->len)) { + if (!nft_payload_copy_vlan(dest, skb, + priv->offset, priv->len)) + goto err; +@@ -810,21 +801,79 @@ struct nft_payload_set { + u8 csum_flags; + }; + ++/* This is not struct vlan_hdr. */ ++struct nft_payload_vlan_hdr { ++ __be16 h_vlan_proto; ++ __be16 h_vlan_TCI; ++}; ++ ++static bool ++nft_payload_set_vlan(const u32 *src, struct sk_buff *skb, u8 offset, u8 len, ++ int *vlan_hlen) ++{ ++ struct nft_payload_vlan_hdr *vlanh; ++ __be16 vlan_proto; ++ u16 vlan_tci; ++ ++ if (offset >= offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto)) { ++ *vlan_hlen = VLAN_HLEN; ++ return true; ++ } ++ ++ switch (offset) { ++ case offsetof(struct vlan_ethhdr, h_vlan_proto): ++ if (len == 2) { ++ vlan_proto = nft_reg_load_be16(src); ++ skb->vlan_proto = vlan_proto; ++ } else if (len == 4) { ++ vlanh = (struct nft_payload_vlan_hdr *)src; ++ __vlan_hwaccel_put_tag(skb, vlanh->h_vlan_proto, ++ ntohs(vlanh->h_vlan_TCI)); ++ } else { ++ return false; ++ } ++ break; ++ case offsetof(struct vlan_ethhdr, h_vlan_TCI): ++ if (len != 2) ++ return false; ++ ++ vlan_tci = ntohs(nft_reg_load_be16(src)); ++ skb->vlan_tci = vlan_tci; ++ break; ++ default: ++ return false; ++ } ++ ++ return true; ++} ++ + static void nft_payload_set_eval(const struct nft_expr *expr, + struct nft_regs *regs, + const struct nft_pktinfo *pkt) + { + const struct nft_payload_set *priv = nft_expr_priv(expr); +- struct sk_buff *skb = pkt->skb; + const u32 *src = ®s->data[priv->sreg]; +- int offset, csum_offset; ++ int offset, csum_offset, vlan_hlen = 0; ++ struct sk_buff *skb = pkt->skb; + __wsum fsum, tsum; + + switch (priv->base) { + case NFT_PAYLOAD_LL_HEADER: + if (!skb_mac_header_was_set(skb)) + goto err; +- offset = skb_mac_header(skb) - skb->data; ++ ++ if (skb_vlan_tag_present(skb) && ++ nft_payload_need_vlan_adjust(priv->offset, priv->len)) { ++ if (!nft_payload_set_vlan(src, skb, ++ priv->offset, priv->len, ++ &vlan_hlen)) ++ goto err; ++ ++ if (!vlan_hlen) ++ return; ++ } ++ ++ offset = skb_mac_header(skb) - skb->data - vlan_hlen; + break; + case NFT_PAYLOAD_NETWORK_HEADER: + offset = skb_network_offset(skb); +diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c +index 24d9771385729..14d88394bcb7f 100644 +--- a/net/netfilter/nft_rt.c ++++ b/net/netfilter/nft_rt.c +@@ -73,14 +73,14 @@ void nft_rt_get_eval(const struct nft_expr *expr, + if (nft_pf(pkt) != NFPROTO_IPV4) + goto err; + +- *dest = (__force u32)rt_nexthop((const struct rtable *)dst, ++ *dest = (__force u32)rt_nexthop(dst_rtable(dst), + ip_hdr(skb)->daddr); + break; + case NFT_RT_NEXTHOP6: + if (nft_pf(pkt) != NFPROTO_IPV6) + goto err; + +- memcpy(dest, rt6_nexthop((struct rt6_info *)dst, ++ memcpy(dest, rt6_nexthop(dst_rt6_info(dst), + &ipv6_hdr(skb)->daddr), + sizeof(struct in6_addr)); + break; +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index b133dc55304ce..f456a5911e7d1 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -1463,6 +1463,19 @@ int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode, + ndev->ops->n_core_ops); + } + ++static bool nci_valid_size(struct sk_buff *skb) ++{ ++ BUILD_BUG_ON(NCI_CTRL_HDR_SIZE != NCI_DATA_HDR_SIZE); ++ unsigned int hdr_size = NCI_CTRL_HDR_SIZE; ++ ++ if (skb->len < hdr_size || ++ !nci_plen(skb->data) || ++ skb->len < hdr_size + nci_plen(skb->data)) { ++ return false; ++ } ++ return true; ++} ++ + /* ---- NCI TX Data worker thread ---- */ + + static void nci_tx_work(struct work_struct *work) +@@ -1516,10 +1529,9 @@ static void nci_rx_work(struct work_struct *work) + nfc_send_to_raw_sock(ndev->nfc_dev, skb, + RAW_PAYLOAD_NCI, NFC_DIRECTION_RX); + +- if (!nci_plen(skb->data)) { ++ if (!nci_valid_size(skb)) { + kfree_skb(skb); +- kcov_remote_stop(); +- break; ++ continue; + } + + /* Process frame */ +diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c +index 6fcd7e2ca81fe..9642255808247 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -936,6 +936,12 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, + pskb_trim(skb, ovs_mac_header_len(key)); + } + ++ /* Need to set the pkt_type to involve the routing layer. The ++ * packet movement through the OVS datapath doesn't generally ++ * use routing, but this is needed for tunnel cases. ++ */ ++ skb->pkt_type = PACKET_OUTGOING; ++ + if (likely(!mru || + (skb->len <= mru + vport->dev->hard_header_len))) { + ovs_vport_send(vport, skb, ovs_key_mac_proto(key)); +diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c +index a0d54b422186f..5c3f8a278fc2f 100644 +--- a/net/sched/sch_taprio.c ++++ b/net/sched/sch_taprio.c +@@ -1151,11 +1151,6 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb, + list_for_each_entry(entry, &new->entries, list) + cycle = ktime_add_ns(cycle, entry->interval); + +- if (!cycle) { +- NL_SET_ERR_MSG(extack, "'cycle_time' can never be 0"); +- return -EINVAL; +- } +- + if (cycle < 0 || cycle > INT_MAX) { + NL_SET_ERR_MSG(extack, "'cycle_time' is too big"); + return -EINVAL; +@@ -1164,6 +1159,11 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb, + new->cycle_time = cycle; + } + ++ if (new->cycle_time < new->num_entries * length_to_duration(q, ETH_ZLEN)) { ++ NL_SET_ERR_MSG(extack, "'cycle_time' is too small"); ++ return -EINVAL; ++ } ++ + taprio_calculate_gate_durations(q, new); + + return 0; +@@ -1851,6 +1851,9 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt, + } + q->flags = taprio_flags; + ++ /* Needed for length_to_duration() during netlink attribute parsing */ ++ taprio_set_picos_per_byte(dev, q); ++ + err = taprio_parse_mqprio_opt(dev, mqprio, extack, q->flags); + if (err < 0) + return err; +@@ -1910,7 +1913,6 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt, + if (err < 0) + goto free_sched; + +- taprio_set_picos_per_byte(dev, q); + taprio_update_queue_max_sdu(q, new_admin, stab); + + if (FULL_OFFLOAD_IS_ENABLED(q->flags)) +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 24368f755ab19..f7b809c0d142c 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -415,7 +415,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + if (!IS_ERR_OR_NULL(dst)) { + struct rt6_info *rt; + +- rt = (struct rt6_info *)dst; ++ rt = dst_rt6_info(dst); + t->dst_cookie = rt6_get_cookie(rt); + pr_debug("rt6_dst:%pI6/%d rt6_src:%pI6\n", + &rt->rt6i_dst.addr, rt->rt6i_dst.plen, +diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c +index e849f368ed913..5a7436a13b741 100644 +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -552,7 +552,7 @@ static void sctp_v4_get_saddr(struct sctp_sock *sk, + struct flowi *fl) + { + union sctp_addr *saddr = &t->saddr; +- struct rtable *rt = (struct rtable *)t->dst; ++ struct rtable *rt = dst_rtable(t->dst); + + if (rt) { + saddr->v4.sin_family = AF_INET; +@@ -1085,7 +1085,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, struct sctp_transport *t) + skb_reset_inner_mac_header(skb); + skb_reset_inner_transport_header(skb); + skb_set_inner_ipproto(skb, IPPROTO_SCTP); +- udp_tunnel_xmit_skb((struct rtable *)dst, sk, skb, fl4->saddr, ++ udp_tunnel_xmit_skb(dst_rtable(dst), sk, skb, fl4->saddr, + fl4->daddr, dscp, ip4_dst_hoplimit(dst), df, + sctp_sk(sk)->udp_port, t->encap_port, false, false); + return 0; +diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c +index 96ab50eda9c2e..73a90ad873fb9 100644 +--- a/net/sunrpc/auth_gss/svcauth_gss.c ++++ b/net/sunrpc/auth_gss/svcauth_gss.c +@@ -1069,7 +1069,7 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp, + goto out_denied_free; + + pages = DIV_ROUND_UP(inlen, PAGE_SIZE); +- in_token->pages = kcalloc(pages, sizeof(struct page *), GFP_KERNEL); ++ in_token->pages = kcalloc(pages + 1, sizeof(struct page *), GFP_KERNEL); + if (!in_token->pages) + goto out_denied_free; + in_token->page_base = 0; +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 28f3749f6dc6c..59b2fbd88e5eb 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -1071,6 +1071,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, + .authflavor = old->cl_auth->au_flavor, + .cred = old->cl_cred, + .stats = old->cl_stats, ++ .timeout = old->cl_timeout, + }; + struct rpc_clnt *clnt; + int err; +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index 4f8d7efa469f0..432557a553e7e 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -244,7 +244,11 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) + case RDMA_CM_EVENT_DEVICE_REMOVAL: + pr_info("rpcrdma: removing device %s for %pISpc\n", + ep->re_id->device->name, sap); +- fallthrough; ++ switch (xchg(&ep->re_connect_status, -ENODEV)) { ++ case 0: goto wake_connect_worker; ++ case 1: goto disconnected; ++ } ++ return 0; + case RDMA_CM_EVENT_ADDR_CHANGE: + ep->re_connect_status = -ENODEV; + goto disconnected; +diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c +index f892b0903dbaf..b849a3d133a01 100644 +--- a/net/tipc/udp_media.c ++++ b/net/tipc/udp_media.c +@@ -174,7 +174,7 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, + local_bh_disable(); + ndst = dst_cache_get(cache); + if (dst->proto == htons(ETH_P_IP)) { +- struct rtable *rt = (struct rtable *)ndst; ++ struct rtable *rt = dst_rtable(ndst); + + if (!rt) { + struct flowi4 fl = { +diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c +index b4674f03d71a9..90b7f253d3632 100644 +--- a/net/tls/tls_main.c ++++ b/net/tls/tls_main.c +@@ -816,9 +816,17 @@ struct tls_context *tls_ctx_create(struct sock *sk) + return NULL; + + mutex_init(&ctx->tx_lock); +- rcu_assign_pointer(icsk->icsk_ulp_data, ctx); + ctx->sk_proto = READ_ONCE(sk->sk_prot); + ctx->sk = sk; ++ /* Release semantic of rcu_assign_pointer() ensures that ++ * ctx->sk_proto is visible before changing sk->sk_prot in ++ * update_sk_prot(), and prevents reading uninitialized value in ++ * tls_{getsockopt, setsockopt}. Note that we do not need a ++ * read barrier in tls_{getsockopt,setsockopt} as there is an ++ * address dependency between sk->sk_proto->{getsockopt,setsockopt} ++ * and ctx->sk_proto. ++ */ ++ rcu_assign_pointer(icsk->icsk_ulp_data, ctx); + return ctx; + } + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index e94839d89b09d..439c531744a27 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -731,7 +731,7 @@ static int unix_listen(struct socket *sock, int backlog) + if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) + goto out; /* Only stream/seqpacket sockets accept */ + err = -EINVAL; +- if (!u->addr) ++ if (!READ_ONCE(u->addr)) + goto out; /* No listens on an unbound socket */ + unix_state_lock(sk); + if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN) +@@ -1131,8 +1131,8 @@ static struct sock *unix_find_other(struct net *net, + + static int unix_autobind(struct sock *sk) + { +- unsigned int new_hash, old_hash = sk->sk_hash; + struct unix_sock *u = unix_sk(sk); ++ unsigned int new_hash, old_hash; + struct net *net = sock_net(sk); + struct unix_address *addr; + u32 lastnum, ordernum; +@@ -1155,6 +1155,7 @@ static int unix_autobind(struct sock *sk) + addr->name->sun_family = AF_UNIX; + refcount_set(&addr->refcnt, 1); + ++ old_hash = sk->sk_hash; + ordernum = get_random_u32(); + lastnum = ordernum & 0xFFFFF; + retry: +@@ -1195,8 +1196,8 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr, + { + umode_t mode = S_IFSOCK | + (SOCK_INODE(sk->sk_socket)->i_mode & ~current_umask()); +- unsigned int new_hash, old_hash = sk->sk_hash; + struct unix_sock *u = unix_sk(sk); ++ unsigned int new_hash, old_hash; + struct net *net = sock_net(sk); + struct mnt_idmap *idmap; + struct unix_address *addr; +@@ -1234,6 +1235,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr, + if (u->addr) + goto out_unlock; + ++ old_hash = sk->sk_hash; + new_hash = unix_bsd_hash(d_backing_inode(dentry)); + unix_table_double_lock(net, old_hash, new_hash); + u->path.mnt = mntget(parent.mnt); +@@ -1261,8 +1263,8 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr, + static int unix_bind_abstract(struct sock *sk, struct sockaddr_un *sunaddr, + int addr_len) + { +- unsigned int new_hash, old_hash = sk->sk_hash; + struct unix_sock *u = unix_sk(sk); ++ unsigned int new_hash, old_hash; + struct net *net = sock_net(sk); + struct unix_address *addr; + int err; +@@ -1280,6 +1282,7 @@ static int unix_bind_abstract(struct sock *sk, struct sockaddr_un *sunaddr, + goto out_mutex; + } + ++ old_hash = sk->sk_hash; + new_hash = unix_abstract_hash(addr->name, addr->len, sk->sk_type); + unix_table_double_lock(net, old_hash, new_hash); + +@@ -1369,7 +1372,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, + + if ((test_bit(SOCK_PASSCRED, &sock->flags) || + test_bit(SOCK_PASSPIDFD, &sock->flags)) && +- !unix_sk(sk)->addr) { ++ !READ_ONCE(unix_sk(sk)->addr)) { + err = unix_autobind(sk); + if (err) + goto out; +@@ -1481,7 +1484,8 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, + goto out; + + if ((test_bit(SOCK_PASSCRED, &sock->flags) || +- test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) { ++ test_bit(SOCK_PASSPIDFD, &sock->flags)) && ++ !READ_ONCE(u->addr)) { + err = unix_autobind(sk); + if (err) + goto out; +@@ -1997,7 +2001,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, + } + + if ((test_bit(SOCK_PASSCRED, &sock->flags) || +- test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) { ++ test_bit(SOCK_PASSPIDFD, &sock->flags)) && ++ !READ_ONCE(u->addr)) { + err = unix_autobind(sk); + if (err) + goto out; +@@ -2217,13 +2222,15 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other + maybe_add_creds(skb, sock, other); + skb_get(skb); + ++ scm_stat_add(other, skb); ++ ++ spin_lock(&other->sk_receive_queue.lock); + if (ousk->oob_skb) + consume_skb(ousk->oob_skb); +- + WRITE_ONCE(ousk->oob_skb, skb); ++ __skb_queue_tail(&other->sk_receive_queue, skb); ++ spin_unlock(&other->sk_receive_queue.lock); + +- scm_stat_add(other, skb); +- skb_queue_tail(&other->sk_receive_queue, skb); + sk_send_sigurg(other); + unix_state_unlock(other); + other->sk_data_ready(other); +@@ -2614,8 +2621,10 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state) + + mutex_lock(&u->iolock); + unix_state_lock(sk); ++ spin_lock(&sk->sk_receive_queue.lock); + + if (sock_flag(sk, SOCK_URGINLINE) || !u->oob_skb) { ++ spin_unlock(&sk->sk_receive_queue.lock); + unix_state_unlock(sk); + mutex_unlock(&u->iolock); + return -EINVAL; +@@ -2627,6 +2636,8 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state) + WRITE_ONCE(u->oob_skb, NULL); + else + skb_get(oob_skb); ++ ++ spin_unlock(&sk->sk_receive_queue.lock); + unix_state_unlock(sk); + + chunk = state->recv_actor(oob_skb, 0, chunk, state); +@@ -2655,6 +2666,10 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, + consume_skb(skb); + skb = NULL; + } else { ++ struct sk_buff *unlinked_skb = NULL; ++ ++ spin_lock(&sk->sk_receive_queue.lock); ++ + if (skb == u->oob_skb) { + if (copied) { + skb = NULL; +@@ -2666,13 +2681,19 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, + } else if (flags & MSG_PEEK) { + skb = NULL; + } else { +- skb_unlink(skb, &sk->sk_receive_queue); ++ __skb_unlink(skb, &sk->sk_receive_queue); + WRITE_ONCE(u->oob_skb, NULL); +- if (!WARN_ON_ONCE(skb_unref(skb))) +- kfree_skb(skb); ++ unlinked_skb = skb; + skb = skb_peek(&sk->sk_receive_queue); + } + } ++ ++ spin_unlock(&sk->sk_receive_queue.lock); ++ ++ if (unlinked_skb) { ++ WARN_ON_ONCE(skb_unref(unlinked_skb)); ++ kfree_skb(unlinked_skb); ++ } + } + return skb; + } +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 53d8fabfa6858..d154597728d51 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -2598,8 +2598,7 @@ static void xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst, + int nfheader_len) + { + if (dst->ops->family == AF_INET6) { +- struct rt6_info *rt = (struct rt6_info *)dst; +- path->path_cookie = rt6_get_cookie(rt); ++ path->path_cookie = rt6_get_cookie(dst_rt6_info(dst)); + path->u.rt6.rt6i_nfheader_len = nfheader_len; + } + } +@@ -3905,15 +3904,10 @@ static void xfrm_link_failure(struct sk_buff *skb) + /* Impossible. Such dst must be popped before reaches point of failure. */ + } + +-static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) ++static void xfrm_negative_advice(struct sock *sk, struct dst_entry *dst) + { +- if (dst) { +- if (dst->obsolete) { +- dst_release(dst); +- dst = NULL; +- } +- } +- return dst; ++ if (dst->obsolete) ++ sk_dst_reset(sk); + } + + static void xfrm_init_pmtu(struct xfrm_dst **bundle, int nr) +diff --git a/scripts/Makefile.vdsoinst b/scripts/Makefile.vdsoinst +index c477d17b0aa5b..a81ca735003e4 100644 +--- a/scripts/Makefile.vdsoinst ++++ b/scripts/Makefile.vdsoinst +@@ -21,7 +21,7 @@ $$(dest): $$(src) FORCE + $$(call cmd,install) + + # Some architectures create .build-id symlinks +-ifneq ($(filter arm sparc x86, $(SRCARCH)),) ++ifneq ($(filter arm s390 sparc x86, $(SRCARCH)),) + link := $(install-dir)/.build-id/$$(shell $(READELF) -n $$(src) | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p').debug + + __default: $$(link) +diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c +index 81fe1884ef8ae..67a509778135b 100644 +--- a/scripts/kconfig/symbol.c ++++ b/scripts/kconfig/symbol.c +@@ -14,6 +14,7 @@ + + struct symbol symbol_yes = { + .name = "y", ++ .type = S_TRISTATE, + .curr = { "y", yes }, + .menus = LIST_HEAD_INIT(symbol_yes.menus), + .flags = SYMBOL_CONST|SYMBOL_VALID, +@@ -21,6 +22,7 @@ struct symbol symbol_yes = { + + struct symbol symbol_mod = { + .name = "m", ++ .type = S_TRISTATE, + .curr = { "m", mod }, + .menus = LIST_HEAD_INIT(symbol_mod.menus), + .flags = SYMBOL_CONST|SYMBOL_VALID, +@@ -28,6 +30,7 @@ struct symbol symbol_mod = { + + struct symbol symbol_no = { + .name = "n", ++ .type = S_TRISTATE, + .curr = { "n", no }, + .menus = LIST_HEAD_INIT(symbol_no.menus), + .flags = SYMBOL_CONST|SYMBOL_VALID, +@@ -788,8 +791,7 @@ const char *sym_get_string_value(struct symbol *sym) + case no: + return "n"; + case mod: +- sym_calc_value(modules_sym); +- return (modules_sym->curr.tri == no) ? "n" : "m"; ++ return "m"; + case yes: + return "y"; + } +diff --git a/sound/core/init.c b/sound/core/init.c +index 66d7265fea920..b8912de048662 100644 +--- a/sound/core/init.c ++++ b/sound/core/init.c +@@ -539,6 +539,11 @@ void snd_card_disconnect(struct snd_card *card) + synchronize_irq(card->sync_irq); + + snd_info_card_disconnect(card); ++#ifdef CONFIG_SND_DEBUG ++ debugfs_remove(card->debugfs_root); ++ card->debugfs_root = NULL; ++#endif ++ + if (card->registered) { + device_del(&card->card_dev); + card->registered = false; +@@ -590,10 +595,6 @@ static int snd_card_do_free(struct snd_card *card) + dev_warn(card->dev, "unable to free card info\n"); + /* Not fatal error */ + } +-#ifdef CONFIG_SND_DEBUG +- debugfs_remove(card->debugfs_root); +- card->debugfs_root = NULL; +-#endif + if (card->release_completion) + complete(card->release_completion); + if (!card->managed) +diff --git a/sound/core/jack.c b/sound/core/jack.c +index e08b2c4fbd1a5..e4bcecdf89b7e 100644 +--- a/sound/core/jack.c ++++ b/sound/core/jack.c +@@ -37,11 +37,15 @@ static const int jack_switch_types[SND_JACK_SWITCH_TYPES] = { + }; + #endif /* CONFIG_SND_JACK_INPUT_DEV */ + ++static void snd_jack_remove_debugfs(struct snd_jack *jack); ++ + static int snd_jack_dev_disconnect(struct snd_device *device) + { +-#ifdef CONFIG_SND_JACK_INPUT_DEV + struct snd_jack *jack = device->device_data; + ++ snd_jack_remove_debugfs(jack); ++ ++#ifdef CONFIG_SND_JACK_INPUT_DEV + guard(mutex)(&jack->input_dev_lock); + if (!jack->input_dev) + return 0; +@@ -381,10 +385,14 @@ static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack, + return 0; + } + +-static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl) ++static void snd_jack_remove_debugfs(struct snd_jack *jack) + { +- debugfs_remove(jack_kctl->jack_debugfs_root); +- jack_kctl->jack_debugfs_root = NULL; ++ struct snd_jack_kctl *jack_kctl; ++ ++ list_for_each_entry(jack_kctl, &jack->kctl_list, list) { ++ debugfs_remove(jack_kctl->jack_debugfs_root); ++ jack_kctl->jack_debugfs_root = NULL; ++ } + } + #else /* CONFIG_SND_JACK_INJECTION_DEBUG */ + static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack, +@@ -393,7 +401,7 @@ static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack, + return 0; + } + +-static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl) ++static void snd_jack_remove_debugfs(struct snd_jack *jack) + { + } + #endif /* CONFIG_SND_JACK_INJECTION_DEBUG */ +@@ -404,7 +412,6 @@ static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl) + + jack_kctl = kctl->private_data; + if (jack_kctl) { +- snd_jack_debugfs_clear_inject_node(jack_kctl); + list_del(&jack_kctl->list); + kfree(jack_kctl); + } +@@ -497,8 +504,8 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, + .dev_free = snd_jack_dev_free, + #ifdef CONFIG_SND_JACK_INPUT_DEV + .dev_register = snd_jack_dev_register, +- .dev_disconnect = snd_jack_dev_disconnect, + #endif /* CONFIG_SND_JACK_INPUT_DEV */ ++ .dev_disconnect = snd_jack_dev_disconnect, + }; + + if (initial_kctl) { +diff --git a/sound/core/seq/seq_ump_convert.c b/sound/core/seq/seq_ump_convert.c +index ee6ac649df836..9bfba69b2a709 100644 +--- a/sound/core/seq/seq_ump_convert.c ++++ b/sound/core/seq/seq_ump_convert.c +@@ -157,7 +157,7 @@ static void ump_system_to_one_param_ev(const union snd_ump_midi1_msg *val, + static void ump_system_to_songpos_ev(const union snd_ump_midi1_msg *val, + struct snd_seq_event *ev) + { +- ev->data.control.value = (val->system.parm1 << 7) | val->system.parm2; ++ ev->data.control.value = (val->system.parm2 << 7) | val->system.parm1; + } + + /* Encoders for 0xf0 - 0xff */ +@@ -368,6 +368,7 @@ static int cvt_ump_midi1_to_midi2(struct snd_seq_client *dest, + struct snd_seq_ump_event ev_cvt; + const union snd_ump_midi1_msg *midi1 = (const union snd_ump_midi1_msg *)event->ump; + union snd_ump_midi2_msg *midi2 = (union snd_ump_midi2_msg *)ev_cvt.ump; ++ struct snd_seq_ump_midi2_bank *cc; + + ev_cvt = *event; + memset(&ev_cvt.ump, 0, sizeof(ev_cvt.ump)); +@@ -387,11 +388,29 @@ static int cvt_ump_midi1_to_midi2(struct snd_seq_client *dest, + midi2->paf.data = upscale_7_to_32bit(midi1->paf.data); + break; + case UMP_MSG_STATUS_CC: ++ cc = &dest_port->midi2_bank[midi1->note.channel]; ++ switch (midi1->cc.index) { ++ case UMP_CC_BANK_SELECT: ++ cc->bank_set = 1; ++ cc->cc_bank_msb = midi1->cc.data; ++ return 0; // skip ++ case UMP_CC_BANK_SELECT_LSB: ++ cc->bank_set = 1; ++ cc->cc_bank_lsb = midi1->cc.data; ++ return 0; // skip ++ } + midi2->cc.index = midi1->cc.index; + midi2->cc.data = upscale_7_to_32bit(midi1->cc.data); + break; + case UMP_MSG_STATUS_PROGRAM: + midi2->pg.program = midi1->pg.program; ++ cc = &dest_port->midi2_bank[midi1->note.channel]; ++ if (cc->bank_set) { ++ midi2->pg.bank_valid = 1; ++ midi2->pg.bank_msb = cc->cc_bank_msb; ++ midi2->pg.bank_lsb = cc->cc_bank_lsb; ++ cc->bank_set = 0; ++ } + break; + case UMP_MSG_STATUS_CHANNEL_PRESSURE: + midi2->caf.data = upscale_7_to_32bit(midi1->caf.data); +@@ -419,6 +438,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest, + struct snd_seq_ump_event ev_cvt; + union snd_ump_midi1_msg *midi1 = (union snd_ump_midi1_msg *)ev_cvt.ump; + const union snd_ump_midi2_msg *midi2 = (const union snd_ump_midi2_msg *)event->ump; ++ int err; + u16 v; + + ev_cvt = *event; +@@ -443,6 +463,24 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest, + midi1->cc.data = downscale_32_to_7bit(midi2->cc.data); + break; + case UMP_MSG_STATUS_PROGRAM: ++ if (midi2->pg.bank_valid) { ++ midi1->cc.status = UMP_MSG_STATUS_CC; ++ midi1->cc.index = UMP_CC_BANK_SELECT; ++ midi1->cc.data = midi2->pg.bank_msb; ++ err = __snd_seq_deliver_single_event(dest, dest_port, ++ (struct snd_seq_event *)&ev_cvt, ++ atomic, hop); ++ if (err < 0) ++ return err; ++ midi1->cc.index = UMP_CC_BANK_SELECT_LSB; ++ midi1->cc.data = midi2->pg.bank_lsb; ++ err = __snd_seq_deliver_single_event(dest, dest_port, ++ (struct snd_seq_event *)&ev_cvt, ++ atomic, hop); ++ if (err < 0) ++ return err; ++ midi1->note.status = midi2->note.status; ++ } + midi1->pg.program = midi2->pg.program; + break; + case UMP_MSG_STATUS_CHANNEL_PRESSURE: +@@ -691,6 +729,7 @@ static int system_ev_to_ump_midi1(const struct snd_seq_event *event, + union snd_ump_midi1_msg *data, + unsigned char status) + { ++ data->system.type = UMP_MSG_TYPE_SYSTEM; // override + data->system.status = status; + return 1; + } +@@ -713,8 +752,8 @@ static int system_2p_ev_to_ump_midi1(const struct snd_seq_event *event, + unsigned char status) + { + data->system.status = status; +- data->system.parm1 = (event->data.control.value >> 7) & 0x7f; +- data->system.parm2 = event->data.control.value & 0x7f; ++ data->system.parm1 = event->data.control.value & 0x7f; ++ data->system.parm2 = (event->data.control.value >> 7) & 0x7f; + return 1; + } + +@@ -854,7 +893,6 @@ static int pgm_ev_to_ump_midi2(const struct snd_seq_event *event, + data->pg.bank_msb = cc->cc_bank_msb; + data->pg.bank_lsb = cc->cc_bank_lsb; + cc->bank_set = 0; +- cc->cc_bank_msb = cc->cc_bank_lsb = 0; + } + return 1; + } +diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c +index 558c1f38fe971..11b0570ff56d4 100644 +--- a/sound/pci/hda/cs35l56_hda.c ++++ b/sound/pci/hda/cs35l56_hda.c +@@ -732,8 +732,6 @@ static void cs35l56_hda_unbind(struct device *dev, struct device *master, void * + if (cs35l56->base.fw_patched) + cs_dsp_power_down(&cs35l56->cs_dsp); + +- cs_dsp_remove(&cs35l56->cs_dsp); +- + if (comps[cs35l56->index].dev == dev) + memset(&comps[cs35l56->index], 0, sizeof(*comps)); + +@@ -1035,7 +1033,7 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id) + ARRAY_SIZE(cs35l56_hda_dai_config)); + ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base); + if (ret) +- goto err; ++ goto dsp_err; + + /* + * By default only enable one ASP1TXn, where n=amplifier index, +@@ -1061,6 +1059,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id) + + pm_err: + pm_runtime_disable(cs35l56->base.dev); ++dsp_err: ++ cs_dsp_remove(&cs35l56->cs_dsp); + err: + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + +@@ -1078,6 +1078,8 @@ void cs35l56_hda_remove(struct device *dev) + + component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops); + ++ cs_dsp_remove(&cs35l56->cs_dsp); ++ + kfree(cs35l56->system_name); + pm_runtime_put_noidle(cs35l56->base.dev); + +diff --git a/sound/pci/hda/hda_component.c b/sound/pci/hda/hda_component.c +index cd299d7d84baf..d02589014a3fa 100644 +--- a/sound/pci/hda/hda_component.c ++++ b/sound/pci/hda/hda_component.c +@@ -123,6 +123,21 @@ static int hda_comp_match_dev_name(struct device *dev, void *data) + return !strcmp(d + n, tmp); + } + ++int hda_component_manager_bind(struct hda_codec *cdc, ++ struct hda_component *comps, int count) ++{ ++ int i; ++ ++ /* Init shared data */ ++ for (i = 0; i < count; ++i) { ++ memset(&comps[i], 0, sizeof(comps[i])); ++ comps[i].codec = cdc; ++ } ++ ++ return component_bind_all(hda_codec_dev(cdc), comps); ++} ++EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, SND_HDA_SCODEC_COMPONENT); ++ + int hda_component_manager_init(struct hda_codec *cdc, + struct hda_component *comps, int count, + const char *bus, const char *hid, +@@ -143,7 +158,6 @@ int hda_component_manager_init(struct hda_codec *cdc, + sm->hid = hid; + sm->match_str = match_str; + sm->index = i; +- comps[i].codec = cdc; + component_match_add(dev, &match, hda_comp_match_dev_name, sm); + } + +diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h +index c80a66691b5d8..c70b3de68ab20 100644 +--- a/sound/pci/hda/hda_component.h ++++ b/sound/pci/hda/hda_component.h +@@ -75,11 +75,8 @@ int hda_component_manager_init(struct hda_codec *cdc, + void hda_component_manager_free(struct hda_codec *cdc, + const struct component_master_ops *ops); + +-static inline int hda_component_manager_bind(struct hda_codec *cdc, +- struct hda_component *comps) +-{ +- return component_bind_all(hda_codec_dev(cdc), comps); +-} ++int hda_component_manager_bind(struct hda_codec *cdc, ++ struct hda_component *comps, int count); + + static inline void hda_component_manager_unbind(struct hda_codec *cdc, + struct hda_component *comps) +diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c +index 463ca06036bfe..9db45d7c17e5f 100644 +--- a/sound/pci/hda/hda_cs_dsp_ctl.c ++++ b/sound/pci/hda/hda_cs_dsp_ctl.c +@@ -8,6 +8,7 @@ + + #include <linux/module.h> + #include <sound/soc.h> ++#include <linux/cleanup.h> + #include <linux/firmware/cirrus/cs_dsp.h> + #include <linux/firmware/cirrus/wmfw.h> + #include "hda_cs_dsp_ctl.h" +@@ -97,11 +98,23 @@ static unsigned int wmfw_convert_flags(unsigned int in) + return out; + } + +-static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name) ++static void hda_cs_dsp_free_kcontrol(struct snd_kcontrol *kctl) + { ++ struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl); + struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; ++ ++ /* NULL priv to prevent a double-free in hda_cs_dsp_control_remove() */ ++ cs_ctl->priv = NULL; ++ kfree(ctl); ++} ++ ++static void hda_cs_dsp_add_kcontrol(struct cs_dsp_coeff_ctl *cs_ctl, ++ const struct hda_cs_dsp_ctl_info *info, ++ const char *name) ++{ + struct snd_kcontrol_new kcontrol = {0}; + struct snd_kcontrol *kctl; ++ struct hda_cs_dsp_coeff_ctl *ctl __free(kfree) = NULL; + int ret = 0; + + if (cs_ctl->len > ADSP_MAX_STD_CTRL_SIZE) { +@@ -110,6 +123,13 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char + return; + } + ++ ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); ++ if (!ctl) ++ return; ++ ++ ctl->cs_ctl = cs_ctl; ++ ctl->card = info->card; ++ + kcontrol.name = name; + kcontrol.info = hda_cs_dsp_coeff_info; + kcontrol.iface = SNDRV_CTL_ELEM_IFACE_MIXER; +@@ -117,20 +137,22 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char + kcontrol.get = hda_cs_dsp_coeff_get; + kcontrol.put = hda_cs_dsp_coeff_put; + +- /* Save ctl inside private_data, ctl is owned by cs_dsp, +- * and will be freed when cs_dsp removes the control */ + kctl = snd_ctl_new1(&kcontrol, (void *)ctl); + if (!kctl) + return; + +- ret = snd_ctl_add(ctl->card, kctl); ++ kctl->private_free = hda_cs_dsp_free_kcontrol; ++ ctl->kctl = kctl; ++ ++ /* snd_ctl_add() calls our private_free on error, which will kfree(ctl) */ ++ cs_ctl->priv = no_free_ptr(ctl); ++ ret = snd_ctl_add(info->card, kctl); + if (ret) { + dev_err(cs_ctl->dsp->dev, "Failed to add KControl %s = %d\n", kcontrol.name, ret); + return; + } + + dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol.name); +- ctl->kctl = kctl; + } + + static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, +@@ -138,7 +160,6 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, + { + struct cs_dsp *cs_dsp = cs_ctl->dsp; + char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +- struct hda_cs_dsp_coeff_ctl *ctl; + const char *region_name; + int ret; + +@@ -163,15 +184,7 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, + " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip); + } + +- ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); +- if (!ctl) +- return; +- +- ctl->cs_ctl = cs_ctl; +- ctl->card = info->card; +- cs_ctl->priv = ctl; +- +- hda_cs_dsp_add_kcontrol(ctl, name); ++ hda_cs_dsp_add_kcontrol(cs_ctl, info, name); + } + + void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info) +@@ -203,7 +216,9 @@ void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl) + { + struct hda_cs_dsp_coeff_ctl *ctl = cs_ctl->priv; + +- kfree(ctl); ++ /* ctl and kctl may already have been removed by ALSA private_free */ ++ if (ctl && ctl->kctl) ++ snd_ctl_remove(ctl->card, ctl->kctl); + } + EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS); + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 3b8b4ab488a61..1a1ca7caaff07 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6793,7 +6793,7 @@ static int comp_bind(struct device *dev) + struct alc_spec *spec = cdc->spec; + int ret; + +- ret = hda_component_manager_bind(cdc, spec->comps); ++ ret = hda_component_manager_bind(cdc, spec->comps, ARRAY_SIZE(spec->comps)); + if (ret) + return ret; + +@@ -10103,7 +10103,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8a2c, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8a2d, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8a2e, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2), +- SND_PCI_QUIRK(0x103c, 0x8a2e, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8a30, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8a31, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8a6e, "HP EDNA 360", ALC287_FIXUP_CS35L41_I2C_4), +@@ -10295,7 +10294,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), + SND_PCI_QUIRK(0x1043, 0x3a20, "ASUS G614JZR", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1043, 0x3a30, "ASUS G814JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2), +- SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC245_FIXUP_CS35L41_SPI_2), ++ SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), + SND_PCI_QUIRK(0x1043, 0x3a50, "ASUS G834JYR/JZR", ALC245_FIXUP_CS35L41_SPI_2), + SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), + SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), +diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c +index b5aff3f230be5..3be7c6d55a6f8 100644 +--- a/sound/soc/amd/acp/acp-legacy-common.c ++++ b/sound/soc/amd/acp/acp-legacy-common.c +@@ -358,11 +358,25 @@ int smn_read(struct pci_dev *dev, u32 smn_addr) + } + EXPORT_SYMBOL_NS_GPL(smn_read, SND_SOC_ACP_COMMON); + +-int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip) ++static void check_acp3x_config(struct acp_chip_info *chip) + { +- struct acpi_device *pdm_dev; +- const union acpi_object *obj; +- u32 pdm_addr, val; ++ u32 val; ++ ++ val = readl(chip->base + ACP3X_PIN_CONFIG); ++ switch (val) { ++ case ACP_CONFIG_4: ++ chip->is_i2s_config = true; ++ chip->is_pdm_config = true; ++ break; ++ default: ++ chip->is_pdm_config = true; ++ break; ++ } ++} ++ ++static void check_acp6x_config(struct acp_chip_info *chip) ++{ ++ u32 val; + + val = readl(chip->base + ACP_PIN_CONFIG); + switch (val) { +@@ -371,42 +385,94 @@ int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip) + case ACP_CONFIG_6: + case ACP_CONFIG_7: + case ACP_CONFIG_8: +- case ACP_CONFIG_10: + case ACP_CONFIG_11: ++ case ACP_CONFIG_14: ++ chip->is_pdm_config = true; ++ break; ++ case ACP_CONFIG_9: ++ chip->is_i2s_config = true; ++ break; ++ case ACP_CONFIG_10: + case ACP_CONFIG_12: + case ACP_CONFIG_13: ++ chip->is_i2s_config = true; ++ chip->is_pdm_config = true; ++ break; ++ default: ++ break; ++ } ++} ++ ++static void check_acp70_config(struct acp_chip_info *chip) ++{ ++ u32 val; ++ ++ val = readl(chip->base + ACP_PIN_CONFIG); ++ switch (val) { ++ case ACP_CONFIG_4: ++ case ACP_CONFIG_5: ++ case ACP_CONFIG_6: ++ case ACP_CONFIG_7: ++ case ACP_CONFIG_8: ++ case ACP_CONFIG_11: + case ACP_CONFIG_14: ++ case ACP_CONFIG_17: ++ case ACP_CONFIG_18: ++ chip->is_pdm_config = true; ++ break; ++ case ACP_CONFIG_9: ++ chip->is_i2s_config = true; ++ break; ++ case ACP_CONFIG_10: ++ case ACP_CONFIG_12: ++ case ACP_CONFIG_13: ++ case ACP_CONFIG_19: ++ case ACP_CONFIG_20: ++ chip->is_i2s_config = true; ++ chip->is_pdm_config = true; + break; + default: +- return -EINVAL; ++ break; + } ++} ++ ++void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) ++{ ++ struct acpi_device *pdm_dev; ++ const union acpi_object *obj; ++ u32 pdm_addr; + + switch (chip->acp_rev) { + case ACP3X_DEV: + pdm_addr = ACP_RENOIR_PDM_ADDR; ++ check_acp3x_config(chip); + break; + case ACP6X_DEV: + pdm_addr = ACP_REMBRANDT_PDM_ADDR; ++ check_acp6x_config(chip); + break; + case ACP63_DEV: + pdm_addr = ACP63_PDM_ADDR; ++ check_acp6x_config(chip); + break; + case ACP70_DEV: + pdm_addr = ACP70_PDM_ADDR; ++ check_acp70_config(chip); + break; + default: +- return -EINVAL; ++ break; + } + +- pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0); +- if (pdm_dev) { +- if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type", +- ACPI_TYPE_INTEGER, &obj) && +- obj->integer.value == pdm_addr) +- return 0; ++ if (chip->is_pdm_config) { ++ pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0); ++ if (pdm_dev) { ++ if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type", ++ ACPI_TYPE_INTEGER, &obj) && ++ obj->integer.value == pdm_addr) ++ chip->is_pdm_dev = true; ++ } + } +- return -ENODEV; + } +-EXPORT_SYMBOL_NS_GPL(check_acp_pdm, SND_SOC_ACP_COMMON); ++EXPORT_SYMBOL_NS_GPL(check_acp_config, SND_SOC_ACP_COMMON); + + MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c +index 5f35b90eab8d3..ad320b29e87dc 100644 +--- a/sound/soc/amd/acp/acp-pci.c ++++ b/sound/soc/amd/acp/acp-pci.c +@@ -100,7 +100,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id + ret = -EINVAL; + goto release_regions; + } +- + dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); + if (IS_ERR(dmic_dev)) { + dev_err(dev, "failed to create DMIC device\n"); +@@ -119,6 +118,10 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id + if (ret) + goto unregister_dmic_dev; + ++ check_acp_config(pci, chip); ++ if (!chip->is_pdm_dev && !chip->is_i2s_config) ++ goto skip_pdev_creation; ++ + res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL); + if (!res) { + ret = -ENOMEM; +@@ -136,10 +139,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id + } + } + +- ret = check_acp_pdm(pci, chip); +- if (ret < 0) +- goto skip_pdev_creation; +- + chip->flag = flag; + memset(&pdevinfo, 0, sizeof(pdevinfo)); + +diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h +index 5017e868f39b9..d75b4eb34de8d 100644 +--- a/sound/soc/amd/acp/amd.h ++++ b/sound/soc/amd/acp/amd.h +@@ -138,6 +138,9 @@ struct acp_chip_info { + void __iomem *base; /* ACP memory PCI base */ + struct platform_device *chip_pdev; + unsigned int flag; /* Distinguish b/w Legacy or Only PDM */ ++ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */ ++ bool is_pdm_config; /* flag set to true when PDM configuration is selected from BIOS */ ++ bool is_i2s_config; /* flag set to true when I2S configuration is selected from BIOS */ + }; + + struct acp_stream { +@@ -212,6 +215,11 @@ enum acp_config { + ACP_CONFIG_13, + ACP_CONFIG_14, + ACP_CONFIG_15, ++ ACP_CONFIG_16, ++ ACP_CONFIG_17, ++ ACP_CONFIG_18, ++ ACP_CONFIG_19, ++ ACP_CONFIG_20, + }; + + extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops; +@@ -240,7 +248,7 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream, + int restore_acp_i2s_params(struct snd_pcm_substream *substream, + struct acp_dev_data *adata, struct acp_stream *stream); + +-int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip); ++void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip); + + static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction) + { +diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h +index cfd6c4d075944..18da734c0e9e7 100644 +--- a/sound/soc/amd/acp/chip_offset_byte.h ++++ b/sound/soc/amd/acp/chip_offset_byte.h +@@ -20,6 +20,7 @@ + #define ACP_SOFT_RESET 0x1000 + #define ACP_CONTROL 0x1004 + #define ACP_PIN_CONFIG 0x1440 ++#define ACP3X_PIN_CONFIG 0x1400 + + #define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \ + (adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04)) +diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c +index 94685449f0f48..92674314227c4 100644 +--- a/sound/soc/codecs/cs42l43.c ++++ b/sound/soc/codecs/cs42l43.c +@@ -310,8 +310,9 @@ static int cs42l43_startup(struct snd_pcm_substream *substream, struct snd_soc_d + struct snd_soc_component *component = dai->component; + struct cs42l43_codec *priv = snd_soc_component_get_drvdata(component); + struct cs42l43 *cs42l43 = priv->core; +- int provider = !!regmap_test_bits(cs42l43->regmap, CS42L43_ASP_CLK_CONFIG2, +- CS42L43_ASP_MASTER_MODE_MASK); ++ int provider = !dai->id || !!regmap_test_bits(cs42l43->regmap, ++ CS42L43_ASP_CLK_CONFIG2, ++ CS42L43_ASP_MASTER_MODE_MASK); + + if (provider) + priv->constraint.mask = CS42L43_PROVIDER_RATE_MASK; +diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c +index ee450126106f9..9a55e77af02fe 100644 +--- a/sound/soc/codecs/rt715-sdca-sdw.c ++++ b/sound/soc/codecs/rt715-sdca-sdw.c +@@ -234,10 +234,10 @@ static int __maybe_unused rt715_dev_resume(struct device *dev) + if (!slave->unattach_request) + goto regmap_sync; + +- time = wait_for_completion_timeout(&slave->enumeration_complete, ++ time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(RT715_PROBE_TIMEOUT)); + if (!time) { +- dev_err(&slave->dev, "%s: Enumeration not complete, timed out\n", __func__); ++ dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); + sdw_show_ping_status(slave->bus, true); + + return -ETIMEDOUT; +diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c +index 8c9dc318b0e82..c65a4219ecd6c 100644 +--- a/sound/soc/codecs/tas2552.c ++++ b/sound/soc/codecs/tas2552.c +@@ -2,7 +2,8 @@ + /* + * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier + * +- * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com ++ * Copyright (C) 2014 - 2024 Texas Instruments Incorporated - ++ * https://www.ti.com + * + * Author: Dan Murphy <dmurphy@ti.com> + */ +@@ -119,12 +120,14 @@ static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] = + &tas2552_input_mux_control), + + SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("ASI OUT", "DAC Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0), + SND_SOC_DAPM_POST("Post Event", tas2552_post_event), + +- SND_SOC_DAPM_OUTPUT("OUT") ++ SND_SOC_DAPM_OUTPUT("OUT"), ++ SND_SOC_DAPM_INPUT("DMIC") + }; + + static const struct snd_soc_dapm_route tas2552_audio_map[] = { +@@ -134,6 +137,7 @@ static const struct snd_soc_dapm_route tas2552_audio_map[] = { + {"ClassD", NULL, "Input selection"}, + {"OUT", NULL, "ClassD"}, + {"ClassD", NULL, "PLL"}, ++ {"ASI OUT", NULL, "DMIC"} + }; + + #ifdef CONFIG_PM +@@ -538,6 +542,13 @@ static struct snd_soc_dai_driver tas2552_dai[] = { + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS2552_FORMATS, + }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = TAS2552_FORMATS, ++ }, + .ops = &tas2552_speaker_dai_ops, + }, + }; +diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c +index 45760fe195237..265a8ca25cbbe 100644 +--- a/sound/soc/codecs/tas2781-fmwlib.c ++++ b/sound/soc/codecs/tas2781-fmwlib.c +@@ -1,8 +1,8 @@ + // SPDX-License-Identifier: GPL-2.0 + // +-// tasdevice-fmw.c -- TASDEVICE firmware support ++// tas2781-fmwlib.c -- TASDEVICE firmware support + // +-// Copyright 2023 Texas Instruments, Inc. ++// Copyright 2023 - 2024 Texas Instruments, Inc. + // + // Author: Shenghao Ding <shenghao-ding@ti.com> + +@@ -1878,7 +1878,7 @@ int tas2781_load_calibration(void *context, char *file_name, + { + struct tasdevice_priv *tas_priv = (struct tasdevice_priv *)context; + struct tasdevice *tasdev = &(tas_priv->tasdevice[i]); +- const struct firmware *fw_entry; ++ const struct firmware *fw_entry = NULL; + struct tasdevice_fw *tas_fmw; + struct firmware fmw; + int offset = 0; +@@ -2151,6 +2151,24 @@ static int tasdevice_load_data(struct tasdevice_priv *tas_priv, + return ret; + } + ++static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i) ++{ ++ struct tasdevice_calibration *cal; ++ struct tasdevice_fw *cal_fmw; ++ ++ cal_fmw = priv->tasdevice[i].cali_data_fmw; ++ ++ /* No calibrated data for current devices, playback will go ahead. */ ++ if (!cal_fmw) ++ return; ++ ++ cal = cal_fmw->calibrations; ++ if (cal) ++ return; ++ ++ load_calib_data(priv, &cal->dev_data); ++} ++ + int tasdevice_select_tuningprm_cfg(void *context, int prm_no, + int cfg_no, int rca_conf_no) + { +@@ -2210,21 +2228,9 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no, + for (i = 0; i < tas_priv->ndev; i++) { + if (tas_priv->tasdevice[i].is_loaderr == true) + continue; +- else if (tas_priv->tasdevice[i].is_loaderr == false +- && tas_priv->tasdevice[i].is_loading == true) { +- struct tasdevice_fw *cal_fmw = +- tas_priv->tasdevice[i].cali_data_fmw; +- +- if (cal_fmw) { +- struct tasdevice_calibration +- *cal = cal_fmw->calibrations; +- +- if (cal) +- load_calib_data(tas_priv, +- &(cal->dev_data)); +- } ++ if (tas_priv->tasdevice[i].is_loaderr == false && ++ tas_priv->tasdevice[i].is_loading == true) + tas_priv->tasdevice[i].cur_prog = prm_no; +- } + } + } + +@@ -2245,11 +2251,15 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no, + tasdevice_load_data(tas_priv, &(conf->dev_data)); + for (i = 0; i < tas_priv->ndev; i++) { + if (tas_priv->tasdevice[i].is_loaderr == true) { +- status |= 1 << (i + 4); ++ status |= BIT(i + 4); + continue; +- } else if (tas_priv->tasdevice[i].is_loaderr == false +- && tas_priv->tasdevice[i].is_loading == true) ++ } ++ ++ if (tas_priv->tasdevice[i].is_loaderr == false && ++ tas_priv->tasdevice[i].is_loading == true) { ++ tasdev_load_calibrated_data(tas_priv, i); + tas_priv->tasdevice[i].cur_conf = cfg_no; ++ } + } + } else + dev_dbg(tas_priv->dev, "%s: Unneeded loading dsp conf %d\n", +@@ -2308,65 +2318,6 @@ int tasdevice_prmg_load(void *context, int prm_no) + } + EXPORT_SYMBOL_NS_GPL(tasdevice_prmg_load, SND_SOC_TAS2781_FMWLIB); + +-int tasdevice_prmg_calibdata_load(void *context, int prm_no) +-{ +- struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context; +- struct tasdevice_fw *tas_fmw = tas_priv->fmw; +- struct tasdevice_prog *program; +- int prog_status = 0; +- int i; +- +- if (!tas_fmw) { +- dev_err(tas_priv->dev, "%s: Firmware is NULL\n", __func__); +- goto out; +- } +- +- if (prm_no >= tas_fmw->nr_programs) { +- dev_err(tas_priv->dev, +- "%s: prm(%d) is not in range of Programs %u\n", +- __func__, prm_no, tas_fmw->nr_programs); +- goto out; +- } +- +- for (i = 0, prog_status = 0; i < tas_priv->ndev; i++) { +- if (prm_no >= 0 && tas_priv->tasdevice[i].cur_prog != prm_no) { +- tas_priv->tasdevice[i].cur_conf = -1; +- tas_priv->tasdevice[i].is_loading = true; +- prog_status++; +- } +- tas_priv->tasdevice[i].is_loaderr = false; +- } +- +- if (prog_status) { +- program = &(tas_fmw->programs[prm_no]); +- tasdevice_load_data(tas_priv, &(program->dev_data)); +- for (i = 0; i < tas_priv->ndev; i++) { +- if (tas_priv->tasdevice[i].is_loaderr == true) +- continue; +- else if (tas_priv->tasdevice[i].is_loaderr == false +- && tas_priv->tasdevice[i].is_loading == true) { +- struct tasdevice_fw *cal_fmw = +- tas_priv->tasdevice[i].cali_data_fmw; +- +- if (cal_fmw) { +- struct tasdevice_calibration *cal = +- cal_fmw->calibrations; +- +- if (cal) +- load_calib_data(tas_priv, +- &(cal->dev_data)); +- } +- tas_priv->tasdevice[i].cur_prog = prm_no; +- } +- } +- } +- +-out: +- return prog_status; +-} +-EXPORT_SYMBOL_NS_GPL(tasdevice_prmg_calibdata_load, +- SND_SOC_TAS2781_FMWLIB); +- + void tasdevice_tuning_switch(void *context, int state) + { + struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context; +diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c +index b5abff230e437..9350972dfefe7 100644 +--- a/sound/soc/codecs/tas2781-i2c.c ++++ b/sound/soc/codecs/tas2781-i2c.c +@@ -2,7 +2,7 @@ + // + // ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier + // +-// Copyright (C) 2022 - 2023 Texas Instruments Incorporated ++// Copyright (C) 2022 - 2024 Texas Instruments Incorporated + // https://www.ti.com + // + // The TAS2563/TAS2781 driver implements a flexible and configurable +@@ -414,7 +414,7 @@ static void tasdevice_fw_ready(const struct firmware *fmw, + __func__, tas_priv->cal_binaryname[i]); + } + +- tasdevice_prmg_calibdata_load(tas_priv, 0); ++ tasdevice_prmg_load(tas_priv, 0); + tas_priv->cur_prog = 0; + out: + if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) { +diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +index 9ce06821c7d0f..49440db370af0 100644 +--- a/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c ++++ b/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c +@@ -566,10 +566,10 @@ static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, + tdm_con |= 1 << DELAY_DATA_SFT; + tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT; + } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_A) { +- tdm_con |= 0 << DELAY_DATA_SFT; ++ tdm_con |= 1 << DELAY_DATA_SFT; + tdm_con |= 0 << LRCK_TDM_WIDTH_SFT; + } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_B) { +- tdm_con |= 1 << DELAY_DATA_SFT; ++ tdm_con |= 0 << DELAY_DATA_SFT; + tdm_con |= 0 << LRCK_TDM_WIDTH_SFT; + } + +diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c +index 7275437ea8d8a..6481da31826dc 100644 +--- a/sound/soc/sof/debug.c ++++ b/sound/soc/sof/debug.c +@@ -345,8 +345,27 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) + + debugfs_create_str("fw_path", 0444, fw_profile, + (char **)&plat_data->fw_filename_prefix); +- debugfs_create_str("fw_lib_path", 0444, fw_profile, +- (char **)&plat_data->fw_lib_prefix); ++ /* library path is not valid for IPC3 */ ++ if (plat_data->ipc_type != SOF_IPC_TYPE_3) { ++ /* ++ * fw_lib_prefix can be NULL if the vendor/platform does not ++ * support loadable libraries ++ */ ++ if (plat_data->fw_lib_prefix) { ++ debugfs_create_str("fw_lib_path", 0444, fw_profile, ++ (char **)&plat_data->fw_lib_prefix); ++ } else { ++ static char *fw_lib_path; ++ ++ fw_lib_path = devm_kasprintf(sdev->dev, GFP_KERNEL, ++ "Not supported"); ++ if (!fw_lib_path) ++ return -ENOMEM; ++ ++ debugfs_create_str("fw_lib_path", 0444, fw_profile, ++ (char **)&fw_lib_path); ++ } ++ } + debugfs_create_str("tplg_path", 0444, fw_profile, + (char **)&plat_data->tplg_filename_prefix); + debugfs_create_str("fw_name", 0444, fw_profile, +diff --git a/tools/arch/x86/intel_sdsi/intel_sdsi.c b/tools/arch/x86/intel_sdsi/intel_sdsi.c +index 2cd92761f1714..ba2a6b6645ae8 100644 +--- a/tools/arch/x86/intel_sdsi/intel_sdsi.c ++++ b/tools/arch/x86/intel_sdsi/intel_sdsi.c +@@ -43,7 +43,6 @@ + #define METER_CERT_MAX_SIZE 4096 + #define STATE_MAX_NUM_LICENSES 16 + #define STATE_MAX_NUM_IN_BUNDLE (uint32_t)8 +-#define METER_MAX_NUM_BUNDLES 8 + + #define __round_mask(x, y) ((__typeof__(x))((y) - 1)) + #define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1) +@@ -154,11 +153,12 @@ struct bundle_encoding { + }; + + struct meter_certificate { +- uint32_t block_signature; +- uint32_t counter_unit; ++ uint32_t signature; ++ uint32_t version; + uint64_t ppin; ++ uint32_t counter_unit; + uint32_t bundle_length; +- uint32_t reserved; ++ uint64_t reserved; + uint32_t mmrc_encoding; + uint32_t mmrc_counter; + }; +@@ -167,6 +167,11 @@ struct bundle_encoding_counter { + uint32_t encoding; + uint32_t counter; + }; ++#define METER_BUNDLE_SIZE sizeof(struct bundle_encoding_counter) ++#define BUNDLE_COUNT(length) ((length) / METER_BUNDLE_SIZE) ++#define METER_MAX_NUM_BUNDLES \ ++ ((METER_CERT_MAX_SIZE - sizeof(struct meter_certificate)) / \ ++ sizeof(struct bundle_encoding_counter)) + + struct sdsi_dev { + struct sdsi_regs regs; +@@ -334,6 +339,7 @@ static int sdsi_meter_cert_show(struct sdsi_dev *s) + uint32_t count = 0; + FILE *cert_ptr; + int ret, size; ++ char name[4]; + + ret = sdsi_update_registers(s); + if (ret) +@@ -375,32 +381,40 @@ static int sdsi_meter_cert_show(struct sdsi_dev *s) + printf("\n"); + printf("Meter certificate for device %s\n", s->dev_name); + printf("\n"); +- printf("Block Signature: 0x%x\n", mc->block_signature); +- printf("Count Unit: %dms\n", mc->counter_unit); +- printf("PPIN: 0x%lx\n", mc->ppin); +- printf("Feature Bundle Length: %d\n", mc->bundle_length); +- printf("MMRC encoding: %d\n", mc->mmrc_encoding); +- printf("MMRC counter: %d\n", mc->mmrc_counter); +- if (mc->bundle_length % 8) { ++ ++ get_feature(mc->signature, name); ++ printf("Signature: %.4s\n", name); ++ ++ printf("Version: %d\n", mc->version); ++ printf("Count Unit: %dms\n", mc->counter_unit); ++ printf("PPIN: 0x%lx\n", mc->ppin); ++ printf("Feature Bundle Length: %d\n", mc->bundle_length); ++ ++ get_feature(mc->mmrc_encoding, name); ++ printf("MMRC encoding: %.4s\n", name); ++ ++ printf("MMRC counter: %d\n", mc->mmrc_counter); ++ if (mc->bundle_length % METER_BUNDLE_SIZE) { + fprintf(stderr, "Invalid bundle length\n"); + return -1; + } + +- if (mc->bundle_length > METER_MAX_NUM_BUNDLES * 8) { +- fprintf(stderr, "More than %d bundles: %d\n", +- METER_MAX_NUM_BUNDLES, mc->bundle_length / 8); ++ if (mc->bundle_length > METER_MAX_NUM_BUNDLES * METER_BUNDLE_SIZE) { ++ fprintf(stderr, "More than %ld bundles: actual %ld\n", ++ METER_MAX_NUM_BUNDLES, BUNDLE_COUNT(mc->bundle_length)); + return -1; + } + +- bec = (void *)(mc) + sizeof(mc); ++ bec = (struct bundle_encoding_counter *)(mc + 1); + +- printf("Number of Feature Counters: %d\n", mc->bundle_length / 8); +- while (count++ < mc->bundle_length / 8) { ++ printf("Number of Feature Counters: %ld\n", BUNDLE_COUNT(mc->bundle_length)); ++ while (count < BUNDLE_COUNT(mc->bundle_length)) { + char feature[5]; + + feature[4] = '\0'; + get_feature(bec[count].encoding, feature); + printf(" %s: %d\n", feature, bec[count].counter); ++ ++count; + } + + return 0; +diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c +index d9520cb826b31..af393c7dee1f1 100644 +--- a/tools/bpf/resolve_btfids/main.c ++++ b/tools/bpf/resolve_btfids/main.c +@@ -728,7 +728,7 @@ static int sets_patch(struct object *obj) + + static int symbols_patch(struct object *obj) + { +- int err; ++ off_t err; + + if (__symbols_patch(obj, &obj->structs) || + __symbols_patch(obj, &obj->unions) || +diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c +index 9fa75943f2ed1..d943d78b787ed 100644 +--- a/tools/lib/subcmd/parse-options.c ++++ b/tools/lib/subcmd/parse-options.c +@@ -633,11 +633,10 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o + const char *const subcommands[], const char *usagestr[], int flags) + { + struct parse_opt_ctx_t ctx; ++ char *buf = NULL; + + /* build usage string if it's not provided */ + if (subcommands && !usagestr[0]) { +- char *buf = NULL; +- + astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]); + + for (int i = 0; subcommands[i]; i++) { +@@ -679,7 +678,10 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o + astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt); + usage_with_options(usagestr, options); + } +- ++ if (buf) { ++ usagestr[0] = NULL; ++ free(buf); ++ } + return parse_options_end(&ctx); + } + +diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt +index 3b12595193c9f..6bf2468f59d31 100644 +--- a/tools/perf/Documentation/perf-list.txt ++++ b/tools/perf/Documentation/perf-list.txt +@@ -71,6 +71,7 @@ counted. The following modifiers exist: + D - pin the event to the PMU + W - group is weak and will fallback to non-group if not schedulable, + e - group or event are exclusive and do not share the PMU ++ b - use BPF aggregration (see perf stat --bpf-counters) + + The 'p' modifier can be used for specifying how precise the instruction + address should be. The 'p' modifier can be specified multiple times: +diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf +index 04d89d2ed209b..d769aa447fb75 100644 +--- a/tools/perf/Makefile.perf ++++ b/tools/perf/Makefile.perf +@@ -458,18 +458,19 @@ SHELL = $(SHELL_PATH) + + arm64_gen_sysreg_dir := $(srctree)/tools/arch/arm64/tools + ifneq ($(OUTPUT),) +- arm64_gen_sysreg_outdir := $(OUTPUT) ++ arm64_gen_sysreg_outdir := $(abspath $(OUTPUT)) + else + arm64_gen_sysreg_outdir := $(CURDIR) + endif + + arm64-sysreg-defs: FORCE +- $(Q)$(MAKE) -C $(arm64_gen_sysreg_dir) O=$(arm64_gen_sysreg_outdir) ++ $(Q)$(MAKE) -C $(arm64_gen_sysreg_dir) O=$(arm64_gen_sysreg_outdir) \ ++ prefix= subdir= + + arm64-sysreg-defs-clean: + $(call QUIET_CLEAN,arm64-sysreg-defs) + $(Q)$(MAKE) -C $(arm64_gen_sysreg_dir) O=$(arm64_gen_sysreg_outdir) \ +- clean > /dev/null ++ prefix= subdir= clean > /dev/null + + beauty_linux_dir := $(srctree)/tools/perf/trace/beauty/include/linux/ + linux_uapi_dir := $(srctree)/tools/include/uapi/linux +diff --git a/tools/perf/bench/inject-buildid.c b/tools/perf/bench/inject-buildid.c +index 49331743c7439..a759eb2328bea 100644 +--- a/tools/perf/bench/inject-buildid.c ++++ b/tools/perf/bench/inject-buildid.c +@@ -362,7 +362,7 @@ static int inject_build_id(struct bench_data *data, u64 *max_rss) + return -1; + + for (i = 0; i < nr_mmaps; i++) { +- int idx = rand() % (nr_dsos - 1); ++ int idx = rand() % nr_dsos; + struct bench_dso *dso = &dsos[idx]; + u64 timestamp = rand() % 1000000; + +diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c +index 5c71fdc419dd7..b722ff88fe7de 100644 +--- a/tools/perf/bench/uprobe.c ++++ b/tools/perf/bench/uprobe.c +@@ -47,7 +47,7 @@ static const char * const bench_uprobe_usage[] = { + #define bench_uprobe__attach_uprobe(prog) \ + skel->links.prog = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.prog, \ + /*pid=*/-1, \ +- /*binary_path=*/"/lib64/libc.so.6", \ ++ /*binary_path=*/"libc.so.6", \ + /*func_offset=*/0, \ + /*opts=*/&uprobe_opts); \ + if (!skel->links.prog) { \ +diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c +index 6c1cc797692d9..9cd97fd76bb5e 100644 +--- a/tools/perf/builtin-annotate.c ++++ b/tools/perf/builtin-annotate.c +@@ -809,8 +809,6 @@ int cmd_annotate(int argc, const char **argv) + "Enable symbol demangling"), + OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, + "Enable kernel symbol demangling"), +- OPT_BOOLEAN(0, "group", &symbol_conf.event_group, +- "Show event group information together"), + OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, + "Show a column with the sum of periods"), + OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, +diff --git a/tools/perf/builtin-daemon.c b/tools/perf/builtin-daemon.c +index 83954af36753a..de76bbc50bfbc 100644 +--- a/tools/perf/builtin-daemon.c ++++ b/tools/perf/builtin-daemon.c +@@ -523,7 +523,7 @@ static int daemon_session__control(struct daemon_session *session, + session->base, SESSION_CONTROL); + + control = open(control_path, O_WRONLY|O_NONBLOCK); +- if (!control) ++ if (control < 0) + return -1; + + if (do_ack) { +@@ -532,7 +532,7 @@ static int daemon_session__control(struct daemon_session *session, + session->base, SESSION_ACK); + + ack = open(ack_path, O_RDONLY, O_NONBLOCK); +- if (!ack) { ++ if (ack < 0) { + close(control); + return -1; + } +diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c +index ff7e1d6cfcd2e..6aeae398ec289 100644 +--- a/tools/perf/builtin-record.c ++++ b/tools/perf/builtin-record.c +@@ -1355,8 +1355,6 @@ static int record__open(struct record *rec) + struct record_opts *opts = &rec->opts; + int rc = 0; + +- evlist__config(evlist, opts, &callchain_param); +- + evlist__for_each_entry(evlist, pos) { + try_again: + if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) { +@@ -2483,6 +2481,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) + + evlist__uniquify_name(rec->evlist); + ++ evlist__config(rec->evlist, opts, &callchain_param); ++ + /* Debug message used by test scripts */ + pr_debug3("perf record opening and mmapping events\n"); + if (record__open(rec) != 0) { +@@ -2881,10 +2881,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) + } + #endif + zstd_fini(&session->zstd_data); +- perf_session__delete(session); +- + if (!opts->no_bpf_event) + evlist__stop_sb_thread(rec->sb_evlist); ++ ++ perf_session__delete(session); + return status; + } + +diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c +index dcd93ee5fc24e..5b684d2ab4be5 100644 +--- a/tools/perf/builtin-report.c ++++ b/tools/perf/builtin-report.c +@@ -428,7 +428,7 @@ static int report__setup_sample_type(struct report *rep) + * compatibility, set the bit if it's an old perf data file. + */ + evlist__for_each_entry(session->evlist, evsel) { +- if (strstr(evsel->name, "arm_spe") && ++ if (strstr(evsel__name(evsel), "arm_spe") && + !(sample_type & PERF_SAMPLE_DATA_SRC)) { + evsel->core.attr.sample_type |= PERF_SAMPLE_DATA_SRC; + sample_type |= PERF_SAMPLE_DATA_SRC; +diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c +index b248c433529a8..1bfb223473715 100644 +--- a/tools/perf/builtin-sched.c ++++ b/tools/perf/builtin-sched.c +@@ -2963,8 +2963,11 @@ static int timehist_check_attr(struct perf_sched *sched, + return -1; + } + +- if (sched->show_callchain && !evsel__has_callchain(evsel)) { +- pr_info("Samples do not have callchains.\n"); ++ /* only need to save callchain related to sched_switch event */ ++ if (sched->show_callchain && ++ evsel__name_is(evsel, "sched:sched_switch") && ++ !evsel__has_callchain(evsel)) { ++ pr_info("Samples of sched_switch event do not have callchains.\n"); + sched->show_callchain = 0; + symbol_conf.use_callchain = 0; + } +diff --git a/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json b/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json +index ec2ff78e2b5f2..3ab1d3a6638c4 100644 +--- a/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json ++++ b/tools/perf/pmu-events/arch/s390/cf_z16/transaction.json +@@ -2,71 +2,71 @@ + { + "BriefDescription": "Transaction count", + "MetricName": "transaction", +- "MetricExpr": "TX_C_TEND + TX_NC_TEND + TX_NC_TABORT + TX_C_TABORT_SPECIAL + TX_C_TABORT_NO_SPECIAL" ++ "MetricExpr": "TX_C_TEND + TX_NC_TEND + TX_NC_TABORT + TX_C_TABORT_SPECIAL + TX_C_TABORT_NO_SPECIAL if has_event(TX_C_TEND) else 0" + }, + { + "BriefDescription": "Cycles per Instruction", + "MetricName": "cpi", +- "MetricExpr": "CPU_CYCLES / INSTRUCTIONS" ++ "MetricExpr": "CPU_CYCLES / INSTRUCTIONS if has_event(INSTRUCTIONS) else 0" + }, + { + "BriefDescription": "Problem State Instruction Ratio", + "MetricName": "prbstate", +- "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100" ++ "MetricExpr": "(PROBLEM_STATE_INSTRUCTIONS / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0" + }, + { + "BriefDescription": "Level One Miss per 100 Instructions", + "MetricName": "l1mp", +- "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100" ++ "MetricExpr": "((L1I_DIR_WRITES + L1D_DIR_WRITES) / INSTRUCTIONS) * 100 if has_event(INSTRUCTIONS) else 0" + }, + { + "BriefDescription": "Percentage sourced from Level 2 cache", + "MetricName": "l2p", +- "MetricExpr": "((DCW_REQ + DCW_REQ_IV + ICW_REQ + ICW_REQ_IV) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100" ++ "MetricExpr": "((DCW_REQ + DCW_REQ_IV + ICW_REQ + ICW_REQ_IV) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_REQ) else 0" + }, + { + "BriefDescription": "Percentage sourced from Level 3 on same chip cache", + "MetricName": "l3p", +- "MetricExpr": "((DCW_REQ_CHIP_HIT + DCW_ON_CHIP + DCW_ON_CHIP_IV + DCW_ON_CHIP_CHIP_HIT + ICW_REQ_CHIP_HIT + ICW_ON_CHIP + ICW_ON_CHIP_IV + ICW_ON_CHIP_CHIP_HIT) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100" ++ "MetricExpr": "((DCW_REQ_CHIP_HIT + DCW_ON_CHIP + DCW_ON_CHIP_IV + DCW_ON_CHIP_CHIP_HIT + ICW_REQ_CHIP_HIT + ICW_ON_CHIP + ICW_ON_CHIP_IV + ICW_ON_CHIP_CHIP_HIT) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_REQ_CHIP_HIT) else 0" + }, + { + "BriefDescription": "Percentage sourced from Level 4 Local cache on same book", + "MetricName": "l4lp", +- "MetricExpr": "((DCW_REQ_DRAWER_HIT + DCW_ON_CHIP_DRAWER_HIT + DCW_ON_MODULE + DCW_ON_DRAWER + IDCW_ON_MODULE_IV + IDCW_ON_MODULE_CHIP_HIT + IDCW_ON_MODULE_DRAWER_HIT + IDCW_ON_DRAWER_IV + IDCW_ON_DRAWER_CHIP_HIT + IDCW_ON_DRAWER_DRAWER_HIT + ICW_REQ_DRAWER_HIT + ICW_ON_CHIP_DRAWER_HIT + ICW_ON_MODULE + ICW_ON_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100" ++ "MetricExpr": "((DCW_REQ_DRAWER_HIT + DCW_ON_CHIP_DRAWER_HIT + DCW_ON_MODULE + DCW_ON_DRAWER + IDCW_ON_MODULE_IV + IDCW_ON_MODULE_CHIP_HIT + IDCW_ON_MODULE_DRAWER_HIT + IDCW_ON_DRAWER_IV + IDCW_ON_DRAWER_CHIP_HIT + IDCW_ON_DRAWER_DRAWER_HIT + ICW_REQ_DRAWER_HIT + ICW_ON_CHIP_DRAWER_HIT + ICW_ON_MODULE + ICW_ON_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_REQ_DRAWER_HIT) else 0" + }, + { + "BriefDescription": "Percentage sourced from Level 4 Remote cache on different book", + "MetricName": "l4rp", +- "MetricExpr": "((DCW_OFF_DRAWER + IDCW_OFF_DRAWER_IV + IDCW_OFF_DRAWER_CHIP_HIT + IDCW_OFF_DRAWER_DRAWER_HIT + ICW_OFF_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100" ++ "MetricExpr": "((DCW_OFF_DRAWER + IDCW_OFF_DRAWER_IV + IDCW_OFF_DRAWER_CHIP_HIT + IDCW_OFF_DRAWER_DRAWER_HIT + ICW_OFF_DRAWER) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_OFF_DRAWER) else 0" + }, + { + "BriefDescription": "Percentage sourced from memory", + "MetricName": "memp", +- "MetricExpr": "((DCW_ON_CHIP_MEMORY + DCW_ON_MODULE_MEMORY + DCW_ON_DRAWER_MEMORY + DCW_OFF_DRAWER_MEMORY + ICW_ON_CHIP_MEMORY + ICW_ON_MODULE_MEMORY + ICW_ON_DRAWER_MEMORY + ICW_OFF_DRAWER_MEMORY) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100" ++ "MetricExpr": "((DCW_ON_CHIP_MEMORY + DCW_ON_MODULE_MEMORY + DCW_ON_DRAWER_MEMORY + DCW_OFF_DRAWER_MEMORY + ICW_ON_CHIP_MEMORY + ICW_ON_MODULE_MEMORY + ICW_ON_DRAWER_MEMORY + ICW_OFF_DRAWER_MEMORY) / (L1I_DIR_WRITES + L1D_DIR_WRITES)) * 100 if has_event(DCW_ON_CHIP_MEMORY) else 0" + }, + { + "BriefDescription": "Cycles per Instructions from Finite cache/memory", + "MetricName": "finite_cpi", +- "MetricExpr": "L1C_TLB2_MISSES / INSTRUCTIONS" ++ "MetricExpr": "L1C_TLB2_MISSES / INSTRUCTIONS if has_event(L1C_TLB2_MISSES) else 0" + }, + { + "BriefDescription": "Estimated Instruction Complexity CPI infinite Level 1", + "MetricName": "est_cpi", +- "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS)" ++ "MetricExpr": "(CPU_CYCLES / INSTRUCTIONS) - (L1C_TLB2_MISSES / INSTRUCTIONS) if has_event(INSTRUCTIONS) else 0" + }, + { + "BriefDescription": "Estimated Sourcing Cycles per Level 1 Miss", + "MetricName": "scpl1m", +- "MetricExpr": "L1C_TLB2_MISSES / (L1I_DIR_WRITES + L1D_DIR_WRITES)" ++ "MetricExpr": "L1C_TLB2_MISSES / (L1I_DIR_WRITES + L1D_DIR_WRITES) if has_event(L1C_TLB2_MISSES) else 0" + }, + { + "BriefDescription": "Estimated TLB CPU percentage of Total CPU", + "MetricName": "tlb_percent", +- "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / CPU_CYCLES) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES)) * 100" ++ "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / CPU_CYCLES) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES)) * 100 if has_event(CPU_CYCLES) else 0" + }, + { + "BriefDescription": "Estimated Cycles per TLB Miss", + "MetricName": "tlb_miss", +- "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / (DTLB2_WRITES + ITLB2_WRITES)) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES))" ++ "MetricExpr": "((DTLB2_MISSES + ITLB2_MISSES) / (DTLB2_WRITES + ITLB2_WRITES)) * (L1C_TLB2_MISSES / (L1I_PENALTY_CYCLES + L1D_PENALTY_CYCLES)) if has_event(DTLB2_MISSES) else 0" + } + ] +diff --git a/tools/perf/pmu-events/arch/s390/mapfile.csv b/tools/perf/pmu-events/arch/s390/mapfile.csv +index a918e1af77a57..b22648d127517 100644 +--- a/tools/perf/pmu-events/arch/s390/mapfile.csv ++++ b/tools/perf/pmu-events/arch/s390/mapfile.csv +@@ -5,4 +5,4 @@ Family-model,Version,Filename,EventType + ^IBM.296[45].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_z13,core + ^IBM.390[67].*[13]\.[1-5].[[:xdigit:]]+$,3,cf_z14,core + ^IBM.856[12].*3\.6.[[:xdigit:]]+$,3,cf_z15,core +-^IBM.393[12].*3\.7.[[:xdigit:]]+$,3,cf_z16,core ++^IBM.393[12].*$,3,cf_z16,core +diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c +index d13ee7683d9d8..e05b370b1e2b1 100644 +--- a/tools/perf/tests/builtin-test.c ++++ b/tools/perf/tests/builtin-test.c +@@ -274,11 +274,8 @@ static int finish_test(struct child_test *child_test, int width) + struct test_suite *t = child_test->test; + int i = child_test->test_num; + int subi = child_test->subtest; +- int out = child_test->process.out; + int err = child_test->process.err; +- bool out_done = out <= 0; + bool err_done = err <= 0; +- struct strbuf out_output = STRBUF_INIT; + struct strbuf err_output = STRBUF_INIT; + int ret; + +@@ -290,11 +287,9 @@ static int finish_test(struct child_test *child_test, int width) + pr_info("%3d: %-*s:\n", i + 1, width, test_description(t, -1)); + + /* +- * Busy loop reading from the child's stdout and stderr that are set to +- * be non-blocking until EOF. ++ * Busy loop reading from the child's stdout/stderr that are set to be ++ * non-blocking until EOF. + */ +- if (!out_done) +- fcntl(out, F_SETFL, O_NONBLOCK); + if (!err_done) + fcntl(err, F_SETFL, O_NONBLOCK); + if (verbose > 1) { +@@ -303,11 +298,8 @@ static int finish_test(struct child_test *child_test, int width) + else + pr_info("%3d: %s:\n", i + 1, test_description(t, -1)); + } +- while (!out_done || !err_done) { +- struct pollfd pfds[2] = { +- { .fd = out, +- .events = POLLIN | POLLERR | POLLHUP | POLLNVAL, +- }, ++ while (!err_done) { ++ struct pollfd pfds[1] = { + { .fd = err, + .events = POLLIN | POLLERR | POLLHUP | POLLNVAL, + }, +@@ -317,21 +309,7 @@ static int finish_test(struct child_test *child_test, int width) + + /* Poll to avoid excessive spinning, timeout set for 1000ms. */ + poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/1000); +- if (!out_done && pfds[0].revents) { +- errno = 0; +- len = read(out, buf, sizeof(buf) - 1); +- +- if (len <= 0) { +- out_done = errno != EAGAIN; +- } else { +- buf[len] = '\0'; +- if (verbose > 1) +- fprintf(stdout, "%s", buf); +- else +- strbuf_addstr(&out_output, buf); +- } +- } +- if (!err_done && pfds[1].revents) { ++ if (!err_done && pfds[0].revents) { + errno = 0; + len = read(err, buf, sizeof(buf) - 1); + +@@ -354,14 +332,10 @@ static int finish_test(struct child_test *child_test, int width) + pr_info("%3d.%1d: %s:\n", i + 1, subi + 1, test_description(t, subi)); + else + pr_info("%3d: %s:\n", i + 1, test_description(t, -1)); +- fprintf(stdout, "%s", out_output.buf); + fprintf(stderr, "%s", err_output.buf); + } +- strbuf_release(&out_output); + strbuf_release(&err_output); + print_test_result(t, i, subi, ret, width); +- if (out > 0) +- close(out); + if (err > 0) + close(err); + return 0; +@@ -394,6 +368,7 @@ static int start_test(struct test_suite *test, int i, int subi, struct child_tes + (*child)->process.no_stdout = 1; + (*child)->process.no_stderr = 1; + } else { ++ (*child)->process.stdout_to_stderr = 1; + (*child)->process.out = -1; + (*child)->process.err = -1; + } +diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c +index 7a3a7bbbec714..29d2f3ee4e10f 100644 +--- a/tools/perf/tests/code-reading.c ++++ b/tools/perf/tests/code-reading.c +@@ -637,11 +637,11 @@ static int do_test_code_reading(bool try_kcore) + + evlist__config(evlist, &opts, NULL); + +- evsel = evlist__first(evlist); +- +- evsel->core.attr.comm = 1; +- evsel->core.attr.disabled = 1; +- evsel->core.attr.enable_on_exec = 0; ++ evlist__for_each_entry(evlist, evsel) { ++ evsel->core.attr.comm = 1; ++ evsel->core.attr.disabled = 1; ++ evsel->core.attr.enable_on_exec = 0; ++ } + + ret = evlist__open(evlist); + if (ret < 0) { +diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh +index 65dd852071250..3302ea0b96723 100755 +--- a/tools/perf/tests/shell/test_arm_coresight.sh ++++ b/tools/perf/tests/shell/test_arm_coresight.sh +@@ -188,7 +188,7 @@ arm_cs_etm_snapshot_test() { + + arm_cs_etm_basic_test() { + echo "Recording trace with '$*'" +- perf record -o ${perfdata} "$@" -- ls > /dev/null 2>&1 ++ perf record -o ${perfdata} "$@" -m,8M -- ls > /dev/null 2>&1 + + perf_script_branch_samples ls && + perf_report_branch_samples ls && +diff --git a/tools/perf/tests/workloads/datasym.c b/tools/perf/tests/workloads/datasym.c +index ddd40bc63448a..8e08fc75a973e 100644 +--- a/tools/perf/tests/workloads/datasym.c ++++ b/tools/perf/tests/workloads/datasym.c +@@ -16,6 +16,22 @@ static int datasym(int argc __maybe_unused, const char **argv __maybe_unused) + { + for (;;) { + buf1.data1++; ++ if (buf1.data1 == 123) { ++ /* ++ * Add some 'noise' in the loop to work around errata ++ * 1694299 on Arm N1. ++ * ++ * Bias exists in SPE sampling which can cause the load ++ * and store instructions to be skipped entirely. This ++ * comes and goes randomly depending on the offset the ++ * linker places the datasym loop at in the Perf binary. ++ * With an extra branch in the middle of the loop that ++ * isn't always taken, the instruction stream is no ++ * longer a continuous repeating pattern that interacts ++ * badly with the bias. ++ */ ++ buf1.data1++; ++ } + buf1.data2 += buf1.data1; + } + return 0; +diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c +index 603d11283cbdc..19503e8387385 100644 +--- a/tools/perf/ui/browser.c ++++ b/tools/perf/ui/browser.c +@@ -203,7 +203,7 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser) + void ui_browser__handle_resize(struct ui_browser *browser) + { + ui__refresh_dimensions(false); +- ui_browser__show(browser, browser->title, ui_helpline__current); ++ ui_browser__show(browser, browser->title ?: "", ui_helpline__current); + ui_browser__refresh(browser); + } + +@@ -287,7 +287,8 @@ int ui_browser__show(struct ui_browser *browser, const char *title, + mutex_lock(&ui__lock); + __ui_browser__show_title(browser, title); + +- browser->title = title; ++ free(browser->title); ++ browser->title = strdup(title); + zfree(&browser->helpline); + + va_start(ap, helpline); +@@ -304,6 +305,7 @@ void ui_browser__hide(struct ui_browser *browser) + mutex_lock(&ui__lock); + ui_helpline__pop(); + zfree(&browser->helpline); ++ zfree(&browser->title); + mutex_unlock(&ui__lock); + } + +diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h +index 510ce45540501..6e98d5f8f71cc 100644 +--- a/tools/perf/ui/browser.h ++++ b/tools/perf/ui/browser.h +@@ -21,7 +21,7 @@ struct ui_browser { + u8 extra_title_lines; + int current_color; + void *priv; +- const char *title; ++ char *title; + char *helpline; + const char *no_samples_msg; + void (*refresh_dimensions)(struct ui_browser *browser); +diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c +index 50ca92255ff62..79d082155c2f9 100644 +--- a/tools/perf/util/annotate.c ++++ b/tools/perf/util/annotate.c +@@ -887,10 +887,17 @@ static struct annotated_source *annotated_source__new(void) + + static __maybe_unused void annotated_source__delete(struct annotated_source *src) + { ++ struct hashmap_entry *cur; ++ size_t bkt; ++ + if (src == NULL) + return; + +- hashmap__free(src->samples); ++ if (src->samples) { ++ hashmap__for_each_entry(src->samples, cur, bkt) ++ zfree(&cur->pvalue); ++ hashmap__free(src->samples); ++ } + zfree(&src->histograms); + free(src); + } +@@ -3025,7 +3032,7 @@ void annotation__toggle_full_addr(struct annotation *notes, struct map_symbol *m + annotation__update_column_widths(notes); + } + +-static void annotation__calc_lines(struct annotation *notes, struct map *map, ++static void annotation__calc_lines(struct annotation *notes, struct map_symbol *ms, + struct rb_root *root) + { + struct annotation_line *al; +@@ -3033,6 +3040,7 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map, + + list_for_each_entry(al, ¬es->src->source, node) { + double percent_max = 0.0; ++ u64 addr; + int i; + + for (i = 0; i < al->data_nr; i++) { +@@ -3048,8 +3056,9 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map, + if (percent_max <= 0.5) + continue; + +- al->path = get_srcline(map__dso(map), notes->start + al->offset, NULL, +- false, true, notes->start + al->offset); ++ addr = map__rip_2objdump(ms->map, ms->sym->start); ++ al->path = get_srcline(map__dso(ms->map), addr + al->offset, NULL, ++ false, true, ms->sym->start + al->offset); + insert_source_line(&tmp_root, al); + } + +@@ -3060,7 +3069,7 @@ static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root) + { + struct annotation *notes = symbol__annotation(ms->sym); + +- annotation__calc_lines(notes, ms->map, root); ++ annotation__calc_lines(notes, ms, root); + } + + int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel) +diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c +index 2791126069b4f..f93e57e2fc42e 100644 +--- a/tools/perf/util/dwarf-aux.c ++++ b/tools/perf/util/dwarf-aux.c +@@ -1136,6 +1136,68 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) + return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); + } + ++#if defined(HAVE_DWARF_GETLOCATIONS_SUPPORT) || defined(HAVE_DWARF_CFI_SUPPORT) ++static int reg_from_dwarf_op(Dwarf_Op *op) ++{ ++ switch (op->atom) { ++ case DW_OP_reg0 ... DW_OP_reg31: ++ return op->atom - DW_OP_reg0; ++ case DW_OP_breg0 ... DW_OP_breg31: ++ return op->atom - DW_OP_breg0; ++ case DW_OP_regx: ++ case DW_OP_bregx: ++ return op->number; ++ default: ++ break; ++ } ++ return -1; ++} ++ ++static int offset_from_dwarf_op(Dwarf_Op *op) ++{ ++ switch (op->atom) { ++ case DW_OP_reg0 ... DW_OP_reg31: ++ case DW_OP_regx: ++ return 0; ++ case DW_OP_breg0 ... DW_OP_breg31: ++ return op->number; ++ case DW_OP_bregx: ++ return op->number2; ++ default: ++ break; ++ } ++ return -1; ++} ++ ++static bool check_allowed_ops(Dwarf_Op *ops, size_t nops) ++{ ++ /* The first op is checked separately */ ++ ops++; ++ nops--; ++ ++ /* ++ * It needs to make sure if the location expression matches to the given ++ * register and offset exactly. Thus it rejects any complex expressions ++ * and only allows a few of selected operators that doesn't change the ++ * location. ++ */ ++ while (nops) { ++ switch (ops->atom) { ++ case DW_OP_stack_value: ++ case DW_OP_deref_size: ++ case DW_OP_deref: ++ case DW_OP_piece: ++ break; ++ default: ++ return false; ++ } ++ ops++; ++ nops--; ++ } ++ return true; ++} ++#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT || HAVE_DWARF_CFI_SUPPORT */ ++ + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT + /** + * die_get_var_innermost_scope - Get innermost scope range of given variable DIE +@@ -1280,7 +1342,7 @@ struct find_var_data { + #define DWARF_OP_DIRECT_REGS 32 + + static bool match_var_offset(Dwarf_Die *die_mem, struct find_var_data *data, +- u64 addr_offset, u64 addr_type) ++ u64 addr_offset, u64 addr_type, bool is_pointer) + { + Dwarf_Die type_die; + Dwarf_Word size; +@@ -1294,6 +1356,12 @@ static bool match_var_offset(Dwarf_Die *die_mem, struct find_var_data *data, + if (die_get_real_type(die_mem, &type_die) == NULL) + return false; + ++ if (is_pointer && dwarf_tag(&type_die) == DW_TAG_pointer_type) { ++ /* Get the target type of the pointer */ ++ if (die_get_real_type(&type_die, &type_die) == NULL) ++ return false; ++ } ++ + if (dwarf_aggregate_size(&type_die, &size) < 0) + return false; + +@@ -1305,34 +1373,6 @@ static bool match_var_offset(Dwarf_Die *die_mem, struct find_var_data *data, + return true; + } + +-static bool check_allowed_ops(Dwarf_Op *ops, size_t nops) +-{ +- /* The first op is checked separately */ +- ops++; +- nops--; +- +- /* +- * It needs to make sure if the location expression matches to the given +- * register and offset exactly. Thus it rejects any complex expressions +- * and only allows a few of selected operators that doesn't change the +- * location. +- */ +- while (nops) { +- switch (ops->atom) { +- case DW_OP_stack_value: +- case DW_OP_deref_size: +- case DW_OP_deref: +- case DW_OP_piece: +- break; +- default: +- return false; +- } +- ops++; +- nops--; +- } +- return true; +-} +- + /* Only checks direct child DIEs in the given scope. */ + static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) + { +@@ -1361,31 +1401,38 @@ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) + if (data->is_fbreg && ops->atom == DW_OP_fbreg && + data->offset >= (int)ops->number && + check_allowed_ops(ops, nops) && +- match_var_offset(die_mem, data, data->offset, ops->number)) ++ match_var_offset(die_mem, data, data->offset, ops->number, ++ /*is_pointer=*/false)) + return DIE_FIND_CB_END; + + /* Only match with a simple case */ + if (data->reg < DWARF_OP_DIRECT_REGS) { + /* pointer variables saved in a register 0 to 31 */ + if (ops->atom == (DW_OP_reg0 + data->reg) && +- check_allowed_ops(ops, nops)) ++ check_allowed_ops(ops, nops) && ++ match_var_offset(die_mem, data, data->offset, 0, ++ /*is_pointer=*/true)) + return DIE_FIND_CB_END; + + /* Local variables accessed by a register + offset */ + if (ops->atom == (DW_OP_breg0 + data->reg) && + check_allowed_ops(ops, nops) && +- match_var_offset(die_mem, data, data->offset, ops->number)) ++ match_var_offset(die_mem, data, data->offset, ops->number, ++ /*is_pointer=*/false)) + return DIE_FIND_CB_END; + } else { + /* pointer variables saved in a register 32 or above */ + if (ops->atom == DW_OP_regx && ops->number == data->reg && +- check_allowed_ops(ops, nops)) ++ check_allowed_ops(ops, nops) && ++ match_var_offset(die_mem, data, data->offset, 0, ++ /*is_pointer=*/true)) + return DIE_FIND_CB_END; + + /* Local variables accessed by a register + offset */ + if (ops->atom == DW_OP_bregx && data->reg == ops->number && + check_allowed_ops(ops, nops) && +- match_var_offset(die_mem, data, data->offset, ops->number2)) ++ match_var_offset(die_mem, data, data->offset, ops->number2, ++ /*is_poitner=*/false)) + return DIE_FIND_CB_END; + } + } +@@ -1447,7 +1494,8 @@ static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg) + continue; + + if (check_allowed_ops(ops, nops) && +- match_var_offset(die_mem, data, data->addr, ops->number)) ++ match_var_offset(die_mem, data, data->addr, ops->number, ++ /*is_pointer=*/false)) + return DIE_FIND_CB_END; + } + return DIE_FIND_CB_SIBLING; +@@ -1479,41 +1527,69 @@ Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr pc, + *offset = data.offset; + return result; + } +-#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ + +-#ifdef HAVE_DWARF_CFI_SUPPORT +-static int reg_from_dwarf_op(Dwarf_Op *op) ++static int __die_collect_vars_cb(Dwarf_Die *die_mem, void *arg) + { +- switch (op->atom) { +- case DW_OP_reg0 ... DW_OP_reg31: +- return op->atom - DW_OP_reg0; +- case DW_OP_breg0 ... DW_OP_breg31: +- return op->atom - DW_OP_breg0; +- case DW_OP_regx: +- case DW_OP_bregx: +- return op->number; +- default: +- break; +- } +- return -1; ++ struct die_var_type **var_types = arg; ++ Dwarf_Die type_die; ++ int tag = dwarf_tag(die_mem); ++ Dwarf_Attribute attr; ++ Dwarf_Addr base, start, end; ++ Dwarf_Op *ops; ++ size_t nops; ++ struct die_var_type *vt; ++ ++ if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter) ++ return DIE_FIND_CB_SIBLING; ++ ++ if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) ++ return DIE_FIND_CB_SIBLING; ++ ++ /* ++ * Only collect the first location as it can reconstruct the ++ * remaining state by following the instructions. ++ * start = 0 means it covers the whole range. ++ */ ++ if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0) ++ return DIE_FIND_CB_SIBLING; ++ ++ if (die_get_real_type(die_mem, &type_die) == NULL) ++ return DIE_FIND_CB_SIBLING; ++ ++ vt = malloc(sizeof(*vt)); ++ if (vt == NULL) ++ return DIE_FIND_CB_END; ++ ++ vt->die_off = dwarf_dieoffset(&type_die); ++ vt->addr = start; ++ vt->reg = reg_from_dwarf_op(ops); ++ vt->offset = offset_from_dwarf_op(ops); ++ vt->next = *var_types; ++ *var_types = vt; ++ ++ return DIE_FIND_CB_SIBLING; + } + +-static int offset_from_dwarf_op(Dwarf_Op *op) ++/** ++ * die_collect_vars - Save all variables and parameters ++ * @sc_die: a scope DIE ++ * @var_types: a pointer to save the resulting list ++ * ++ * Save all variables and parameters in the @sc_die and save them to @var_types. ++ * The @var_types is a singly-linked list containing type and location info. ++ * Actual type can be retrieved using dwarf_offdie() with 'die_off' later. ++ * ++ * Callers should free @var_types. ++ */ ++void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types) + { +- switch (op->atom) { +- case DW_OP_reg0 ... DW_OP_reg31: +- case DW_OP_regx: +- return 0; +- case DW_OP_breg0 ... DW_OP_breg31: +- return op->number; +- case DW_OP_bregx: +- return op->number2; +- default: +- break; +- } +- return -1; ++ Dwarf_Die die_mem; ++ ++ die_find_child(sc_die, __die_collect_vars_cb, (void *)var_types, &die_mem); + } ++#endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ + ++#ifdef HAVE_DWARF_CFI_SUPPORT + /** + * die_get_cfa - Get frame base information + * @dwarf: a Dwarf info +diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h +index 85dd527ae1f70..efafd3a1f5b6f 100644 +--- a/tools/perf/util/dwarf-aux.h ++++ b/tools/perf/util/dwarf-aux.h +@@ -135,6 +135,15 @@ void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die, + /* Get the list of including scopes */ + int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes); + ++/* Variable type information */ ++struct die_var_type { ++ struct die_var_type *next; ++ u64 die_off; ++ u64 addr; ++ int reg; ++ int offset; ++}; ++ + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT + + /* Get byte offset range of given variable DIE */ +@@ -150,6 +159,9 @@ Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr pc, + Dwarf_Addr addr, Dwarf_Die *die_mem, + int *offset); + ++/* Save all variables and parameters in this scope */ ++void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types); ++ + #else /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ + + static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, +@@ -178,6 +190,11 @@ static inline Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die __maybe_unu + return NULL; + } + ++static inline void die_collect_vars(Dwarf_Die *sc_die __maybe_unused, ++ struct die_var_type **var_types __maybe_unused) ++{ ++} ++ + #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ + + #ifdef HAVE_DWARF_CFI_SUPPORT +diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +index b450178e3420b..e733f6b1f7ac5 100644 +--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c ++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +@@ -1319,6 +1319,8 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder, bool no_tip) + bool ret = false; + + decoder->state.type &= ~INTEL_PT_BRANCH; ++ decoder->state.insn_op = INTEL_PT_OP_OTHER; ++ decoder->state.insn_len = 0; + + if (decoder->set_fup_cfe_ip || decoder->set_fup_cfe) { + bool ip = decoder->set_fup_cfe_ip; +diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c +index f38893e0b0369..4db9a098f5926 100644 +--- a/tools/perf/util/intel-pt.c ++++ b/tools/perf/util/intel-pt.c +@@ -764,6 +764,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn, + + addr_location__init(&al); + intel_pt_insn->length = 0; ++ intel_pt_insn->op = INTEL_PT_OP_OTHER; + + if (to_ip && *ip == to_ip) + goto out_no_cache; +@@ -898,6 +899,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn, + + if (to_ip && *ip == to_ip) { + intel_pt_insn->length = 0; ++ intel_pt_insn->op = INTEL_PT_OP_OTHER; + goto out_no_cache; + } + +diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c +index 527517db31821..07c22f765fab4 100644 +--- a/tools/perf/util/machine.c ++++ b/tools/perf/util/machine.c +@@ -1549,8 +1549,8 @@ static int machine__update_kernel_mmap(struct machine *machine, + updated = map__get(orig); + + machine->vmlinux_map = updated; +- machine__set_kernel_mmap(machine, start, end); + maps__remove(machine__kernel_maps(machine), orig); ++ machine__set_kernel_mmap(machine, start, end); + err = maps__insert(machine__kernel_maps(machine), updated); + map__put(orig); + +diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/perf_event_attr_fprintf.c +index 8f04d3b7f3ec7..59fbbba796974 100644 +--- a/tools/perf/util/perf_event_attr_fprintf.c ++++ b/tools/perf/util/perf_event_attr_fprintf.c +@@ -7,6 +7,8 @@ + #include <linux/types.h> + #include <linux/perf_event.h> + #include "util/evsel_fprintf.h" ++#include "util/pmu.h" ++#include "util/pmus.h" + #include "trace-event.h" + + struct bit_names { +@@ -75,9 +77,12 @@ static void __p_read_format(char *buf, size_t size, u64 value) + } + + #define ENUM_ID_TO_STR_CASE(x) case x: return (#x); +-static const char *stringify_perf_type_id(u64 value) ++static const char *stringify_perf_type_id(struct perf_pmu *pmu, u32 type) + { +- switch (value) { ++ if (pmu) ++ return pmu->name; ++ ++ switch (type) { + ENUM_ID_TO_STR_CASE(PERF_TYPE_HARDWARE) + ENUM_ID_TO_STR_CASE(PERF_TYPE_SOFTWARE) + ENUM_ID_TO_STR_CASE(PERF_TYPE_TRACEPOINT) +@@ -175,9 +180,9 @@ do { \ + #define print_id_unsigned(_s) PRINT_ID(_s, "%"PRIu64) + #define print_id_hex(_s) PRINT_ID(_s, "%#"PRIx64) + +-static void __p_type_id(char *buf, size_t size, u64 value) ++static void __p_type_id(struct perf_pmu *pmu, char *buf, size_t size, u64 value) + { +- print_id_unsigned(stringify_perf_type_id(value)); ++ print_id_unsigned(stringify_perf_type_id(pmu, value)); + } + + static void __p_config_hw_id(char *buf, size_t size, u64 value) +@@ -217,8 +222,14 @@ static void __p_config_tracepoint_id(char *buf, size_t size, u64 value) + } + #endif + +-static void __p_config_id(char *buf, size_t size, u32 type, u64 value) ++static void __p_config_id(struct perf_pmu *pmu, char *buf, size_t size, u32 type, u64 value) + { ++ const char *name = perf_pmu__name_from_config(pmu, value); ++ ++ if (name) { ++ print_id_hex(name); ++ return; ++ } + switch (type) { + case PERF_TYPE_HARDWARE: + return __p_config_hw_id(buf, size, value); +@@ -246,8 +257,8 @@ static void __p_config_id(char *buf, size_t size, u32 type, u64 value) + #define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) + #define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val) + #define p_read_format(val) __p_read_format(buf, BUF_SIZE, val) +-#define p_type_id(val) __p_type_id(buf, BUF_SIZE, val) +-#define p_config_id(val) __p_config_id(buf, BUF_SIZE, attr->type, val) ++#define p_type_id(val) __p_type_id(pmu, buf, BUF_SIZE, val) ++#define p_config_id(val) __p_config_id(pmu, buf, BUF_SIZE, attr->type, val) + + #define PRINT_ATTRn(_n, _f, _p, _a) \ + do { \ +@@ -262,6 +273,7 @@ do { \ + int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, + attr__fprintf_f attr__fprintf, void *priv) + { ++ struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); + char buf[BUF_SIZE]; + int ret = 0; + +diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c +index f39cbbc1a7ec1..cc349d9cb0f9f 100644 +--- a/tools/perf/util/pmu.c ++++ b/tools/perf/util/pmu.c +@@ -36,6 +36,18 @@ struct perf_pmu perf_pmu__fake = { + + #define UNIT_MAX_LEN 31 /* max length for event unit name */ + ++enum event_source { ++ /* An event loaded from /sys/devices/<pmu>/events. */ ++ EVENT_SRC_SYSFS, ++ /* An event loaded from a CPUID matched json file. */ ++ EVENT_SRC_CPU_JSON, ++ /* ++ * An event loaded from a /sys/devices/<pmu>/identifier matched json ++ * file. ++ */ ++ EVENT_SRC_SYS_JSON, ++}; ++ + /** + * struct perf_pmu_alias - An event either read from sysfs or builtin in + * pmu-events.c, created by parsing the pmu-events json files. +@@ -425,9 +437,30 @@ static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, + { + struct perf_pmu_alias *alias; + +- if (load && !pmu->sysfs_aliases_loaded) +- pmu_aliases_parse(pmu); ++ if (load && !pmu->sysfs_aliases_loaded) { ++ bool has_sysfs_event; ++ char event_file_name[FILENAME_MAX + 8]; ++ ++ /* ++ * Test if alias/event 'name' exists in the PMU's sysfs/events ++ * directory. If not skip parsing the sysfs aliases. Sysfs event ++ * name must be all lower or all upper case. ++ */ ++ scnprintf(event_file_name, sizeof(event_file_name), "events/%s", name); ++ for (size_t i = 7, n = 7 + strlen(name); i < n; i++) ++ event_file_name[i] = tolower(event_file_name[i]); ++ ++ has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name); ++ if (!has_sysfs_event) { ++ for (size_t i = 7, n = 7 + strlen(name); i < n; i++) ++ event_file_name[i] = toupper(event_file_name[i]); ++ ++ has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name); ++ } ++ if (has_sysfs_event) ++ pmu_aliases_parse(pmu); + ++ } + list_for_each_entry(alias, &pmu->aliases, list) { + if (!strcasecmp(alias->name, name)) + return alias; +@@ -500,7 +533,7 @@ static int update_alias(const struct pmu_event *pe, + + static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, + const char *desc, const char *val, FILE *val_fd, +- const struct pmu_event *pe) ++ const struct pmu_event *pe, enum event_source src) + { + struct perf_pmu_alias *alias; + int ret; +@@ -552,25 +585,30 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, + } + snprintf(alias->unit, sizeof(alias->unit), "%s", unit); + } +- if (!pe) { +- /* Update an event from sysfs with json data. */ +- struct update_alias_data data = { +- .pmu = pmu, +- .alias = alias, +- }; +- ++ switch (src) { ++ default: ++ case EVENT_SRC_SYSFS: + alias->from_sysfs = true; + if (pmu->events_table) { ++ /* Update an event from sysfs with json data. */ ++ struct update_alias_data data = { ++ .pmu = pmu, ++ .alias = alias, ++ }; + if (pmu_events_table__find_event(pmu->events_table, pmu, name, + update_alias, &data) == 0) +- pmu->loaded_json_aliases++; ++ pmu->cpu_json_aliases++; + } +- } +- +- if (!pe) + pmu->sysfs_aliases++; +- else +- pmu->loaded_json_aliases++; ++ break; ++ case EVENT_SRC_CPU_JSON: ++ pmu->cpu_json_aliases++; ++ break; ++ case EVENT_SRC_SYS_JSON: ++ pmu->sys_json_aliases++; ++ break; ++ ++ } + list_add_tail(&alias->list, &pmu->aliases); + return 0; + } +@@ -646,7 +684,8 @@ static int pmu_aliases_parse(struct perf_pmu *pmu) + } + + if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL, +- /*val=*/ NULL, file, /*pe=*/ NULL) < 0) ++ /*val=*/ NULL, file, /*pe=*/ NULL, ++ EVENT_SRC_SYSFS) < 0) + pr_debug("Cannot set up %s\n", name); + fclose(file); + } +@@ -900,7 +939,8 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, + { + struct perf_pmu *pmu = vdata; + +- perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe); ++ perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, ++ pe, EVENT_SRC_CPU_JSON); + return 0; + } + +@@ -935,13 +975,14 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, + return 0; + + if (pmu_uncore_alias_match(pe->pmu, pmu->name) && +- pmu_uncore_identifier_match(pe->compat, pmu->id)) { ++ pmu_uncore_identifier_match(pe->compat, pmu->id)) { + perf_pmu__new_alias(pmu, + pe->name, + pe->desc, + pe->event, + /*val_fd=*/ NULL, +- pe); ++ pe, ++ EVENT_SRC_SYS_JSON); + } + + return 0; +@@ -1035,6 +1076,12 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char + pmu->max_precise = pmu_max_precise(dirfd, pmu); + pmu->alias_name = pmu_find_alias_name(pmu, dirfd); + pmu->events_table = perf_pmu__find_events_table(pmu); ++ /* ++ * Load the sys json events/aliases when loading the PMU as each event ++ * may have a different compat regular expression. We therefore can't ++ * know the number of sys json events/aliases without computing the ++ * regular expressions for them all. ++ */ + pmu_add_sys_aliases(pmu); + list_add_tail(&pmu->list, pmus); + +@@ -1632,15 +1679,15 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu) + { + size_t nr; + +- if (!pmu->sysfs_aliases_loaded) +- pmu_aliases_parse(pmu); +- +- nr = pmu->sysfs_aliases; ++ pmu_aliases_parse(pmu); ++ nr = pmu->sysfs_aliases + pmu->sys_json_aliases;; + + if (pmu->cpu_aliases_added) +- nr += pmu->loaded_json_aliases; ++ nr += pmu->cpu_json_aliases; + else if (pmu->events_table) +- nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases; ++ nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases; ++ else ++ assert(pmu->cpu_json_aliases == 0); + + return pmu->selectable ? nr + 1 : nr; + } +@@ -1693,6 +1740,7 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, + struct strbuf sb; + + strbuf_init(&sb, /*hint=*/ 0); ++ pmu_aliases_parse(pmu); + pmu_add_cpu_aliases(pmu); + list_for_each_entry(event, &pmu->aliases, list) { + size_t buf_used; +@@ -2085,3 +2133,22 @@ void perf_pmu__delete(struct perf_pmu *pmu) + zfree(&pmu->id); + free(pmu); + } ++ ++const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config) ++{ ++ struct perf_pmu_alias *event; ++ ++ if (!pmu) ++ return NULL; ++ ++ pmu_aliases_parse(pmu); ++ pmu_add_cpu_aliases(pmu); ++ list_for_each_entry(event, &pmu->aliases, list) { ++ struct perf_event_attr attr = {.config = 0,}; ++ int ret = perf_pmu__config(pmu, &attr, &event->terms, NULL); ++ ++ if (ret == 0 && config == attr.config) ++ return event->name; ++ } ++ return NULL; ++} +diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h +index e35d985206db5..77c59ebc05261 100644 +--- a/tools/perf/util/pmu.h ++++ b/tools/perf/util/pmu.h +@@ -123,8 +123,10 @@ struct perf_pmu { + const struct pmu_events_table *events_table; + /** @sysfs_aliases: Number of sysfs aliases loaded. */ + uint32_t sysfs_aliases; +- /** @sysfs_aliases: Number of json event aliases loaded. */ +- uint32_t loaded_json_aliases; ++ /** @cpu_json_aliases: Number of json event aliases loaded specific to the CPUID. */ ++ uint32_t cpu_json_aliases; ++ /** @sys_json_aliases: Number of json event aliases loaded matching the PMU's identifier. */ ++ uint32_t sys_json_aliases; + /** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */ + bool sysfs_aliases_loaded; + /** +@@ -273,5 +275,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char + struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus); + void perf_pmu__delete(struct perf_pmu *pmu); + struct perf_pmu *perf_pmus__find_core_pmu(void); ++const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config); + + #endif /* __PMU_H */ +diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c +index 2a0ad9ecf0a20..5c12459e9765f 100644 +--- a/tools/perf/util/probe-event.c ++++ b/tools/perf/util/probe-event.c +@@ -11,6 +11,7 @@ + #include <sys/stat.h> + #include <fcntl.h> + #include <errno.h> ++#include <libgen.h> + #include <stdio.h> + #include <unistd.h> + #include <stdlib.h> +diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c +index 075c0f79b1b92..0aeb97c11c030 100644 +--- a/tools/perf/util/python.c ++++ b/tools/perf/util/python.c +@@ -103,6 +103,16 @@ int perf_pmu__scan_file(const struct perf_pmu *pmu, const char *name, const char + return EOF; + } + ++const char *perf_pmu__name_from_config(struct perf_pmu *pmu __maybe_unused, u64 config __maybe_unused) ++{ ++ return NULL; ++} ++ ++struct perf_pmu *perf_pmus__find_by_type(unsigned int type __maybe_unused) ++{ ++ return NULL; ++} ++ + int perf_pmus__num_core_pmus(void) + { + return 1; +diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c +index bfc1d705f4371..91d2f7f65df74 100644 +--- a/tools/perf/util/stat-display.c ++++ b/tools/perf/util/stat-display.c +@@ -1223,6 +1223,9 @@ static void print_metric_headers(struct perf_stat_config *config, + + /* Print metrics headers only */ + evlist__for_each_entry(evlist, counter) { ++ if (config->aggr_mode != AGGR_NONE && counter->metric_leader != counter) ++ continue; ++ + os.evsel = counter; + + perf_stat__print_shadow_stats(config, counter, 0, +diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c +index 9ebdb8e13c0b8..68dbeae8d2bf6 100644 +--- a/tools/perf/util/symbol.c ++++ b/tools/perf/util/symbol.c +@@ -1287,7 +1287,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, + { + struct maps *kmaps = map__kmaps(map); + struct kcore_mapfn_data md; +- struct map *replacement_map = NULL; ++ struct map *map_ref, *replacement_map = NULL; + struct machine *machine; + bool is_64_bit; + int err, fd; +@@ -1365,6 +1365,24 @@ static int dso__load_kcore(struct dso *dso, struct map *map, + if (!replacement_map) + replacement_map = list_entry(md.maps.next, struct map_list_node, node)->map; + ++ /* ++ * Update addresses of vmlinux map. Re-insert it to ensure maps are ++ * correctly ordered. Do this before using maps__merge_in() for the ++ * remaining maps so vmlinux gets split if necessary. ++ */ ++ map_ref = map__get(map); ++ maps__remove(kmaps, map_ref); ++ ++ map__set_start(map_ref, map__start(replacement_map)); ++ map__set_end(map_ref, map__end(replacement_map)); ++ map__set_pgoff(map_ref, map__pgoff(replacement_map)); ++ map__set_mapping_type(map_ref, map__mapping_type(replacement_map)); ++ ++ err = maps__insert(kmaps, map_ref); ++ map__put(map_ref); ++ if (err) ++ goto out_err; ++ + /* Add new maps */ + while (!list_empty(&md.maps)) { + struct map_list_node *new_node = list_entry(md.maps.next, struct map_list_node, node); +@@ -1372,22 +1390,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map, + + list_del_init(&new_node->node); + +- if (RC_CHK_EQUAL(new_map, replacement_map)) { +- struct map *map_ref; +- +- map__set_start(map, map__start(new_map)); +- map__set_end(map, map__end(new_map)); +- map__set_pgoff(map, map__pgoff(new_map)); +- map__set_mapping_type(map, map__mapping_type(new_map)); +- /* Ensure maps are correctly ordered */ +- map_ref = map__get(map); +- maps__remove(kmaps, map_ref); +- err = maps__insert(kmaps, map_ref); +- map__put(map_ref); +- map__put(new_map); +- if (err) +- goto out_err; +- } else { ++ /* skip if replacement_map, already inserted above */ ++ if (!RC_CHK_EQUAL(new_map, replacement_map)) { + /* + * Merge kcore map into existing maps, + * and ensure that current maps (eBPF) +@@ -1969,6 +1973,10 @@ int dso__load(struct dso *dso, struct map *map) + return ret; + } + ++/* ++ * Always takes ownership of vmlinux when vmlinux_allocated == true, even if ++ * it returns an error. ++ */ + int dso__load_vmlinux(struct dso *dso, struct map *map, + const char *vmlinux, bool vmlinux_allocated) + { +@@ -1987,8 +1995,11 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, + else + symtab_type = DSO_BINARY_TYPE__VMLINUX; + +- if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) ++ if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) { ++ if (vmlinux_allocated) ++ free((char *) vmlinux); + return -1; ++ } + + /* + * dso__load_sym() may copy 'dso' which will result in the copies having +@@ -2031,7 +2042,6 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map) + err = dso__load_vmlinux(dso, map, filename, true); + if (err > 0) + goto out; +- free(filename); + } + out: + return err; +@@ -2183,7 +2193,6 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map) + err = dso__load_vmlinux(dso, map, filename, true); + if (err > 0) + return err; +- free(filename); + } + + if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { +diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c +index 1aa8962dcf52c..515726489e36a 100644 +--- a/tools/perf/util/thread.c ++++ b/tools/perf/util/thread.c +@@ -39,12 +39,13 @@ int thread__init_maps(struct thread *thread, struct machine *machine) + + struct thread *thread__new(pid_t pid, pid_t tid) + { +- char *comm_str; +- struct comm *comm; + RC_STRUCT(thread) *_thread = zalloc(sizeof(*_thread)); + struct thread *thread; + + if (ADD_RC_CHK(thread, _thread) != NULL) { ++ struct comm *comm; ++ char comm_str[32]; ++ + thread__set_pid(thread, pid); + thread__set_tid(thread, tid); + thread__set_ppid(thread, -1); +@@ -56,13 +57,8 @@ struct thread *thread__new(pid_t pid, pid_t tid) + init_rwsem(thread__namespaces_lock(thread)); + init_rwsem(thread__comm_lock(thread)); + +- comm_str = malloc(32); +- if (!comm_str) +- goto err_thread; +- +- snprintf(comm_str, 32, ":%d", tid); ++ snprintf(comm_str, sizeof(comm_str), ":%d", tid); + comm = comm__new(comm_str, 0, false); +- free(comm_str); + if (!comm) + goto err_thread; + +@@ -76,7 +72,7 @@ struct thread *thread__new(pid_t pid, pid_t tid) + return thread; + + err_thread: +- free(thread); ++ thread__delete(thread); + return NULL; + } + +diff --git a/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh b/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh +index 6369927e9c378..48395cfd4f958 100644 +--- a/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/mlxsw_lib.sh +@@ -42,7 +42,7 @@ __mlxsw_only_on_spectrum() + local src=$1; shift + + if ! mlxsw_on_spectrum "$rev"; then +- log_test_skip $src:$caller "(Spectrum-$rev only)" ++ log_test_xfail $src:$caller "(Spectrum-$rev only)" + return 1 + fi + } +diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh +index a88d8a8c85f2e..899b6892603fd 100755 +--- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh +@@ -47,7 +47,6 @@ for current_test in ${TESTS:-$ALL_TESTS}; do + RET=0 + target=$(${current_test}_get_target "$should_fail") + if ((target == 0)); then +- log_test_skip "'$current_test' should_fail=$should_fail test" + continue + fi + +diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh +index f981c957f0975..482ebb744ebad 100755 +--- a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh +@@ -52,7 +52,6 @@ for current_test in ${TESTS:-$ALL_TESTS}; do + RET=0 + target=$(${current_test}_get_target "$should_fail") + if ((target == 0)); then +- log_test_skip "'$current_test' [$profile] should_fail=$should_fail test" + continue + fi + ${current_test}_setup_prepare +diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h +index 3c8f2965c2850..b634969cbb6f1 100644 +--- a/tools/testing/selftests/kselftest_harness.h ++++ b/tools/testing/selftests/kselftest_harness.h +@@ -1216,7 +1216,7 @@ void __run_test(struct __fixture_metadata *f, + struct __test_metadata *t) + { + struct __test_xfail *xfail; +- char *test_name; ++ char test_name[1024]; + const char *diagnostic; + + /* reset test struct */ +@@ -1227,12 +1227,8 @@ void __run_test(struct __fixture_metadata *f, + memset(t->env, 0, sizeof(t->env)); + memset(t->results->reason, 0, sizeof(t->results->reason)); + +- if (asprintf(&test_name, "%s%s%s.%s", f->name, +- variant->name[0] ? "." : "", variant->name, t->name) == -1) { +- ksft_print_msg("ERROR ALLOCATING MEMORY\n"); +- t->exit_code = KSFT_FAIL; +- _exit(t->exit_code); +- } ++ snprintf(test_name, sizeof(test_name), "%s%s%s.%s", ++ f->name, variant->name[0] ? "." : "", variant->name, t->name); + + ksft_print_msg(" RUN %s ...\n", test_name); + +@@ -1270,7 +1266,6 @@ void __run_test(struct __fixture_metadata *f, + + ksft_test_result_code(t->exit_code, test_name, + diagnostic ? "%s" : NULL, diagnostic); +- free(test_name); + } + + static int test_harness_run(int argc, char **argv) +diff --git a/tools/testing/selftests/mm/mdwe_test.c b/tools/testing/selftests/mm/mdwe_test.c +index 1e01d3ddc11c5..200bedcdc32e9 100644 +--- a/tools/testing/selftests/mm/mdwe_test.c ++++ b/tools/testing/selftests/mm/mdwe_test.c +@@ -7,7 +7,6 @@ + #include <linux/mman.h> + #include <linux/prctl.h> + +-#define _GNU_SOURCE + #include <stdio.h> + #include <stdlib.h> + #include <sys/auxv.h> +diff --git a/tools/testing/selftests/net/amt.sh b/tools/testing/selftests/net/amt.sh +index 5175a42cbe8a2..7e7ed6c558da9 100755 +--- a/tools/testing/selftests/net/amt.sh ++++ b/tools/testing/selftests/net/amt.sh +@@ -77,6 +77,7 @@ readonly LISTENER=$(mktemp -u listener-XXXXXXXX) + readonly GATEWAY=$(mktemp -u gateway-XXXXXXXX) + readonly RELAY=$(mktemp -u relay-XXXXXXXX) + readonly SOURCE=$(mktemp -u source-XXXXXXXX) ++readonly SMCROUTEDIR="$(mktemp -d)" + ERR=4 + err=0 + +@@ -85,6 +86,11 @@ exit_cleanup() + for ns in "$@"; do + ip netns delete "${ns}" 2>/dev/null || true + done ++ if [ -f "$SMCROUTEDIR/amt.pid" ]; then ++ smcpid=$(< $SMCROUTEDIR/amt.pid) ++ kill $smcpid ++ fi ++ rm -rf $SMCROUTEDIR + + exit $ERR + } +@@ -167,7 +173,7 @@ setup_iptables() + + setup_mcast_routing() + { +- ip netns exec "${RELAY}" smcrouted ++ ip netns exec "${RELAY}" smcrouted -P $SMCROUTEDIR/amt.pid + ip netns exec "${RELAY}" smcroutectl a relay_src \ + 172.17.0.2 239.0.0.1 amtr + ip netns exec "${RELAY}" smcroutectl a relay_src \ +diff --git a/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh b/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh +index a40c0e9bd023c..eef5cbf6eecca 100755 +--- a/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh ++++ b/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh +@@ -73,25 +73,19 @@ setup_v6() { + # namespaces. veth0 is veth-router, veth1 is veth-host. + # first, set up the inteface's link to the namespace + # then, set the interface "up" +- ip -6 -netns ${ROUTER_NS_V6} link add name ${ROUTER_INTF} \ +- type veth peer name ${HOST_INTF} +- +- ip -6 -netns ${ROUTER_NS_V6} link set dev ${ROUTER_INTF} up +- ip -6 -netns ${ROUTER_NS_V6} link set dev ${HOST_INTF} netns \ +- ${HOST_NS_V6} ++ ip -n ${ROUTER_NS_V6} link add name ${ROUTER_INTF} \ ++ type veth peer name ${HOST_INTF} netns ${HOST_NS_V6} + +- ip -6 -netns ${HOST_NS_V6} link set dev ${HOST_INTF} up +- ip -6 -netns ${ROUTER_NS_V6} addr add \ +- ${ROUTER_ADDR_V6}/${PREFIX_WIDTH_V6} dev ${ROUTER_INTF} nodad ++ # Add tc rule to filter out host na message ++ tc -n ${ROUTER_NS_V6} qdisc add dev ${ROUTER_INTF} clsact ++ tc -n ${ROUTER_NS_V6} filter add dev ${ROUTER_INTF} \ ++ ingress protocol ipv6 pref 1 handle 101 \ ++ flower src_ip ${HOST_ADDR_V6} ip_proto icmpv6 type 136 skip_hw action pass + + HOST_CONF=net.ipv6.conf.${HOST_INTF} + ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.ndisc_notify=1 + ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.disable_ipv6=0 +- ip -6 -netns ${HOST_NS_V6} addr add ${HOST_ADDR_V6}/${PREFIX_WIDTH_V6} \ +- dev ${HOST_INTF} +- + ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF} +- + ip netns exec ${ROUTER_NS_V6} sysctl -w \ + ${ROUTER_CONF}.forwarding=1 >/dev/null 2>&1 + ip netns exec ${ROUTER_NS_V6} sysctl -w \ +@@ -99,6 +93,13 @@ setup_v6() { + ip netns exec ${ROUTER_NS_V6} sysctl -w \ + ${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na} \ + >/dev/null 2>&1 ++ ++ ip -n ${ROUTER_NS_V6} link set dev ${ROUTER_INTF} up ++ ip -n ${HOST_NS_V6} link set dev ${HOST_INTF} up ++ ip -n ${ROUTER_NS_V6} addr add ${ROUTER_ADDR_V6}/${PREFIX_WIDTH_V6} \ ++ dev ${ROUTER_INTF} nodad ++ ip -n ${HOST_NS_V6} addr add ${HOST_ADDR_V6}/${PREFIX_WIDTH_V6} \ ++ dev ${HOST_INTF} + set +e + } + +@@ -162,26 +163,6 @@ arp_test_gratuitous_combinations() { + arp_test_gratuitous 2 1 + } + +-cleanup_tcpdump() { +- set -e +- [[ ! -z ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout} +- [[ ! -z ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr} +- tcpdump_stdout= +- tcpdump_stderr= +- set +e +-} +- +-start_tcpdump() { +- set -e +- tcpdump_stdout=`mktemp` +- tcpdump_stderr=`mktemp` +- ip netns exec ${ROUTER_NS_V6} timeout 15s \ +- tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \ +- "icmp6 && icmp6[0] == 136 && src ${HOST_ADDR_V6}" \ +- > ${tcpdump_stdout} 2> /dev/null +- set +e +-} +- + verify_ndisc() { + local accept_untracked_na=$1 + local same_subnet=$2 +@@ -222,8 +203,9 @@ ndisc_test_untracked_advertisements() { + HOST_ADDR_V6=2001:db8:abcd:0012::3 + fi + fi +- setup_v6 $1 $2 +- start_tcpdump ++ setup_v6 $1 ++ slowwait_for_counter 15 1 \ ++ tc_rule_handle_stats_get "dev ${ROUTER_INTF} ingress" 101 ".packets" "-n ${ROUTER_NS_V6}" + + if verify_ndisc $1 $2; then + printf " TEST: %-60s [ OK ]\n" "${test_msg[*]}" +@@ -231,7 +213,6 @@ ndisc_test_untracked_advertisements() { + printf " TEST: %-60s [FAIL]\n" "${test_msg[*]}" + fi + +- cleanup_tcpdump + cleanup_v6 + set +e + } +diff --git a/tools/testing/selftests/net/forwarding/ethtool_rmon.sh b/tools/testing/selftests/net/forwarding/ethtool_rmon.sh +index 41a34a61f7632..e78776db850f1 100755 +--- a/tools/testing/selftests/net/forwarding/ethtool_rmon.sh ++++ b/tools/testing/selftests/net/forwarding/ethtool_rmon.sh +@@ -78,7 +78,7 @@ rmon_histogram() + + for if in $iface $neigh; do + if ! ensure_mtu $if ${bucket[0]}; then +- log_test_skip "$if does not support the required MTU for $step" ++ log_test_xfail "$if does not support the required MTU for $step" + return + fi + done +@@ -93,7 +93,7 @@ rmon_histogram() + jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null) + + if [ $nbuckets -eq 0 ]; then +- log_test_skip "$iface does not support $set histogram counters" ++ log_test_xfail "$iface does not support $set histogram counters" + return + fi + } +diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh +index e579c2e0c462a..e78f11140edd8 100644 +--- a/tools/testing/selftests/net/forwarding/lib.sh ++++ b/tools/testing/selftests/net/forwarding/lib.sh +@@ -38,32 +38,6 @@ fi + + source "$net_forwarding_dir/../lib.sh" + +-# timeout in seconds +-slowwait() +-{ +- local timeout=$1; shift +- +- local start_time="$(date -u +%s)" +- while true +- do +- local out +- out=$("$@") +- local ret=$? +- if ((!ret)); then +- echo -n "$out" +- return 0 +- fi +- +- local current_time="$(date -u +%s)" +- if ((current_time - start_time > timeout)); then +- echo -n "$out" +- return 1 +- fi +- +- sleep 0.1 +- done +-} +- + ############################################################################## + # Sanity checks + +@@ -358,14 +332,24 @@ EXIT_STATUS=0 + # Per-test return value. Clear at the beginning of each test. + RET=0 + ++ret_set_ksft_status() ++{ ++ local ksft_status=$1; shift ++ local msg=$1; shift ++ ++ RET=$(ksft_status_merge $RET $ksft_status) ++ if (( $? )); then ++ retmsg=$msg ++ fi ++} ++ + check_err() + { + local err=$1 + local msg=$2 + +- if [[ $RET -eq 0 && $err -ne 0 ]]; then +- RET=$err +- retmsg=$msg ++ if ((err)); then ++ ret_set_ksft_status $ksft_fail "$msg" + fi + } + +@@ -374,10 +358,7 @@ check_fail() + local err=$1 + local msg=$2 + +- if [[ $RET -eq 0 && $err -eq 0 ]]; then +- RET=1 +- retmsg=$msg +- fi ++ check_err $((!err)) "$msg" + } + + check_err_fail() +@@ -393,6 +374,62 @@ check_err_fail() + fi + } + ++log_test_result() ++{ ++ local test_name=$1; shift ++ local opt_str=$1; shift ++ local result=$1; shift ++ local retmsg=$1; shift ++ ++ printf "TEST: %-60s [%s]\n" "$test_name $opt_str" "$result" ++ if [[ $retmsg ]]; then ++ printf "\t%s\n" "$retmsg" ++ fi ++} ++ ++pause_on_fail() ++{ ++ if [[ $PAUSE_ON_FAIL == yes ]]; then ++ echo "Hit enter to continue, 'q' to quit" ++ read a ++ [[ $a == q ]] && exit 1 ++ fi ++} ++ ++handle_test_result_pass() ++{ ++ local test_name=$1; shift ++ local opt_str=$1; shift ++ ++ log_test_result "$test_name" "$opt_str" " OK " ++} ++ ++handle_test_result_fail() ++{ ++ local test_name=$1; shift ++ local opt_str=$1; shift ++ ++ log_test_result "$test_name" "$opt_str" FAIL "$retmsg" ++ pause_on_fail ++} ++ ++handle_test_result_xfail() ++{ ++ local test_name=$1; shift ++ local opt_str=$1; shift ++ ++ log_test_result "$test_name" "$opt_str" XFAIL "$retmsg" ++ pause_on_fail ++} ++ ++handle_test_result_skip() ++{ ++ local test_name=$1; shift ++ local opt_str=$1; shift ++ ++ log_test_result "$test_name" "$opt_str" SKIP "$retmsg" ++} ++ + log_test() + { + local test_name=$1 +@@ -402,31 +439,28 @@ log_test() + opt_str="($opt_str)" + fi + +- if [[ $RET -ne 0 ]]; then +- EXIT_STATUS=1 +- printf "TEST: %-60s [FAIL]\n" "$test_name $opt_str" +- if [[ ! -z "$retmsg" ]]; then +- printf "\t%s\n" "$retmsg" +- fi +- if [ "${PAUSE_ON_FAIL}" = "yes" ]; then +- echo "Hit enter to continue, 'q' to quit" +- read a +- [ "$a" = "q" ] && exit 1 +- fi +- return 1 ++ if ((RET == ksft_pass)); then ++ handle_test_result_pass "$test_name" "$opt_str" ++ elif ((RET == ksft_xfail)); then ++ handle_test_result_xfail "$test_name" "$opt_str" ++ elif ((RET == ksft_skip)); then ++ handle_test_result_skip "$test_name" "$opt_str" ++ else ++ handle_test_result_fail "$test_name" "$opt_str" + fi + +- printf "TEST: %-60s [ OK ]\n" "$test_name $opt_str" +- return 0 ++ EXIT_STATUS=$(ksft_exit_status_merge $EXIT_STATUS $RET) ++ return $RET + } + + log_test_skip() + { +- local test_name=$1 +- local opt_str=$2 ++ RET=$ksft_skip retmsg= log_test "$@" ++} + +- printf "TEST: %-60s [SKIP]\n" "$test_name $opt_str" +- return 0 ++log_test_xfail() ++{ ++ RET=$ksft_xfail retmsg= log_test "$@" + } + + log_info() +@@ -487,33 +521,6 @@ wait_for_trap() + "$@" | grep -q trap + } + +-until_counter_is() +-{ +- local expr=$1; shift +- local current=$("$@") +- +- echo $((current)) +- ((current $expr)) +-} +- +-busywait_for_counter() +-{ +- local timeout=$1; shift +- local delta=$1; shift +- +- local base=$("$@") +- busywait "$timeout" until_counter_is ">= $((base + delta))" "$@" +-} +- +-slowwait_for_counter() +-{ +- local timeout=$1; shift +- local delta=$1; shift +- +- local base=$("$@") +- slowwait "$timeout" until_counter_is ">= $((base + delta))" "$@" +-} +- + setup_wait_dev() + { + local dev=$1; shift +@@ -819,29 +826,6 @@ link_stats_rx_errors_get() + link_stats_get $1 rx errors + } + +-tc_rule_stats_get() +-{ +- local dev=$1; shift +- local pref=$1; shift +- local dir=$1; shift +- local selector=${1:-.packets}; shift +- +- tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \ +- | jq ".[1].options.actions[].stats$selector" +-} +- +-tc_rule_handle_stats_get() +-{ +- local id=$1; shift +- local handle=$1; shift +- local selector=${1:-.packets}; shift +- local netns=${1:-""}; shift +- +- tc $netns -j -s filter show $id \ +- | jq ".[] | select(.options.handle == $handle) | \ +- .options.actions[0].stats$selector" +-} +- + ethtool_stats_get() + { + local dev=$1; shift +diff --git a/tools/testing/selftests/net/forwarding/router_mpath_nh_lib.sh b/tools/testing/selftests/net/forwarding/router_mpath_nh_lib.sh +index 7e7d62161c345..b2d2c6cecc01e 100644 +--- a/tools/testing/selftests/net/forwarding/router_mpath_nh_lib.sh ++++ b/tools/testing/selftests/net/forwarding/router_mpath_nh_lib.sh +@@ -69,7 +69,7 @@ nh_stats_test_dispatch_swhw() + nh_stats_do_test "HW $what" "$nh1_id" "$nh2_id" "$group_id" \ + nh_stats_get_hw "${mz[@]}" + elif [[ $kind == veth ]]; then +- log_test_skip "HW stats not offloaded on veth topology" ++ log_test_xfail "HW stats not offloaded on veth topology" + fi + } + +diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh +index 56a9454b7ba35..cf7fe4d550dde 100644 +--- a/tools/testing/selftests/net/lib.sh ++++ b/tools/testing/selftests/net/lib.sh +@@ -14,9 +14,50 @@ NS_LIST="" + + ############################################################################## + # Helpers +-busywait() ++ ++__ksft_status_merge() + { +- local timeout=$1; shift ++ local a=$1; shift ++ local b=$1; shift ++ local -A weights ++ local weight=0 ++ ++ local i ++ for i in "$@"; do ++ weights[$i]=$((weight++)) ++ done ++ ++ if [[ ${weights[$a]} > ${weights[$b]} ]]; then ++ echo "$a" ++ return 0 ++ else ++ echo "$b" ++ return 1 ++ fi ++} ++ ++ksft_status_merge() ++{ ++ local a=$1; shift ++ local b=$1; shift ++ ++ __ksft_status_merge "$a" "$b" \ ++ $ksft_pass $ksft_xfail $ksft_skip $ksft_fail ++} ++ ++ksft_exit_status_merge() ++{ ++ local a=$1; shift ++ local b=$1; shift ++ ++ __ksft_status_merge "$a" "$b" \ ++ $ksft_xfail $ksft_pass $ksft_skip $ksft_fail ++} ++ ++loopy_wait() ++{ ++ local sleep_cmd=$1; shift ++ local timeout_ms=$1; shift + + local start_time="$(date -u +%s%3N)" + while true +@@ -30,13 +71,57 @@ busywait() + fi + + local current_time="$(date -u +%s%3N)" +- if ((current_time - start_time > timeout)); then ++ if ((current_time - start_time > timeout_ms)); then + echo -n "$out" + return 1 + fi ++ ++ $sleep_cmd + done + } + ++busywait() ++{ ++ local timeout_ms=$1; shift ++ ++ loopy_wait : "$timeout_ms" "$@" ++} ++ ++# timeout in seconds ++slowwait() ++{ ++ local timeout_sec=$1; shift ++ ++ loopy_wait "sleep 0.1" "$((timeout_sec * 1000))" "$@" ++} ++ ++until_counter_is() ++{ ++ local expr=$1; shift ++ local current=$("$@") ++ ++ echo $((current)) ++ ((current $expr)) ++} ++ ++busywait_for_counter() ++{ ++ local timeout=$1; shift ++ local delta=$1; shift ++ ++ local base=$("$@") ++ busywait "$timeout" until_counter_is ">= $((base + delta))" "$@" ++} ++ ++slowwait_for_counter() ++{ ++ local timeout=$1; shift ++ local delta=$1; shift ++ ++ local base=$("$@") ++ slowwait "$timeout" until_counter_is ">= $((base + delta))" "$@" ++} ++ + cleanup_ns() + { + local ns="" +@@ -96,3 +181,26 @@ setup_ns() + done + NS_LIST="$NS_LIST $ns_list" + } ++ ++tc_rule_stats_get() ++{ ++ local dev=$1; shift ++ local pref=$1; shift ++ local dir=$1; shift ++ local selector=${1:-.packets}; shift ++ ++ tc -j -s filter show dev $dev ${dir:-ingress} pref $pref \ ++ | jq ".[1].options.actions[].stats$selector" ++} ++ ++tc_rule_handle_stats_get() ++{ ++ local id=$1; shift ++ local handle=$1; shift ++ local selector=${1:-.packets}; shift ++ local netns=${1:-""}; shift ++ ++ tc $netns -j -s filter show $id \ ++ | jq ".[] | select(.options.handle == $handle) | \ ++ .options.actions[0].stats$selector" ++} +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index e4403236f6554..1b5722e6166e5 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -125,8 +125,8 @@ init_shapers() + { + local i + for i in $(seq 1 4); do +- tc -n $ns1 qdisc add dev ns1eth$i root netem rate 20mbit delay 1 +- tc -n $ns2 qdisc add dev ns2eth$i root netem rate 20mbit delay 1 ++ tc -n $ns1 qdisc add dev ns1eth$i root netem rate 20mbit delay 1ms ++ tc -n $ns2 qdisc add dev ns2eth$i root netem rate 20mbit delay 1ms + done + } + +@@ -262,6 +262,8 @@ reset() + + TEST_NAME="${1}" + ++ MPTCP_LIB_SUBTEST_FLAKY=0 # reset if modified ++ + if skip_test; then + MPTCP_LIB_TEST_COUNTER=$((MPTCP_LIB_TEST_COUNTER+1)) + last_test_ignored=1 +@@ -449,7 +451,9 @@ reset_with_tcp_filter() + # $1: err msg + fail_test() + { +- ret=${KSFT_FAIL} ++ if ! mptcp_lib_subtest_is_flaky; then ++ ret=${KSFT_FAIL} ++ fi + + if [ ${#} -gt 0 ]; then + print_fail "${@}" +@@ -3178,6 +3182,7 @@ fullmesh_tests() + fastclose_tests() + { + if reset_check_counter "fastclose test" "MPTcpExtMPFastcloseTx"; then ++ MPTCP_LIB_SUBTEST_FLAKY=1 + test_linkfail=1024 fastclose=client \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 0 0 0 +@@ -3186,6 +3191,7 @@ fastclose_tests() + fi + + if reset_check_counter "fastclose server test" "MPTcpExtMPFastcloseRx"; then ++ MPTCP_LIB_SUBTEST_FLAKY=1 + test_linkfail=1024 fastclose=server \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 0 0 0 0 0 0 1 +@@ -3204,6 +3210,7 @@ fail_tests() + { + # single subflow + if reset_with_fail "Infinite map" 1; then ++ MPTCP_LIB_SUBTEST_FLAKY=1 + test_linkfail=128 \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 0 0 0 +1 +0 1 0 1 "$(pedit_action_pkts)" +@@ -3212,7 +3219,8 @@ fail_tests() + + # multiple subflows + if reset_with_fail "MP_FAIL MP_RST" 2; then +- tc -n $ns2 qdisc add dev ns2eth1 root netem rate 1mbit delay 5 ++ MPTCP_LIB_SUBTEST_FLAKY=1 ++ tc -n $ns2 qdisc add dev ns2eth1 root netem rate 1mbit delay 5ms + pm_nl_set_limits $ns1 0 1 + pm_nl_set_limits $ns2 0 1 + pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow +diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh +index 1b23662203881..7322e1e4e5db6 100755 +--- a/tools/testing/selftests/net/mptcp/simult_flows.sh ++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh +@@ -216,8 +216,8 @@ run_test() + shift 4 + local msg=$* + +- [ $delay1 -gt 0 ] && delay1="delay $delay1" || delay1="" +- [ $delay2 -gt 0 ] && delay2="delay $delay2" || delay2="" ++ [ $delay1 -gt 0 ] && delay1="delay ${delay1}ms" || delay1="" ++ [ $delay2 -gt 0 ] && delay2="delay ${delay2}ms" || delay2="" + + for dev in ns1eth1 ns1eth2; do + tc -n $ns1 qdisc del dev $dev root >/dev/null 2>&1 +@@ -243,7 +243,7 @@ run_test() + do_transfer $small $large $time + lret=$? + mptcp_lib_result_code "${lret}" "${msg}" +- if [ $lret -ne 0 ]; then ++ if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then + ret=$lret + [ $bail -eq 0 ] || exit $ret + fi +@@ -253,7 +253,7 @@ run_test() + do_transfer $large $small $time + lret=$? + mptcp_lib_result_code "${lret}" "${msg}" +- if [ $lret -ne 0 ]; then ++ if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then + ret=$lret + [ $bail -eq 0 ] || exit $ret + fi +@@ -286,7 +286,7 @@ run_test 10 10 0 0 "balanced bwidth" + run_test 10 10 1 25 "balanced bwidth with unbalanced delay" + + # we still need some additional infrastructure to pass the following test-cases +-run_test 10 3 0 0 "unbalanced bwidth" ++MPTCP_LIB_SUBTEST_FLAKY=1 run_test 10 3 0 0 "unbalanced bwidth" + run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay" + run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay" + +diff --git a/tools/testing/selftests/powerpc/dexcr/Makefile b/tools/testing/selftests/powerpc/dexcr/Makefile +index 76210f2bcec3c..829ad075b4a44 100644 +--- a/tools/testing/selftests/powerpc/dexcr/Makefile ++++ b/tools/testing/selftests/powerpc/dexcr/Makefile +@@ -3,7 +3,7 @@ TEST_GEN_FILES := lsdexcr + + include ../../lib.mk + +-$(OUTPUT)/hashchk_test: CFLAGS += -fno-pie $(call cc-option,-mno-rop-protect) ++$(OUTPUT)/hashchk_test: CFLAGS += -fno-pie -no-pie $(call cc-option,-mno-rop-protect) + + $(TEST_GEN_PROGS): ../harness.c ../utils.c ./dexcr.c + $(TEST_GEN_FILES): ../utils.c ./dexcr.c +diff --git a/tools/testing/selftests/riscv/hwprobe/.gitignore b/tools/testing/selftests/riscv/hwprobe/.gitignore +index 8113dc3bdd03a..6e384e80ea1a8 100644 +--- a/tools/testing/selftests/riscv/hwprobe/.gitignore ++++ b/tools/testing/selftests/riscv/hwprobe/.gitignore +@@ -1 +1,3 @@ + hwprobe ++cbo ++which-cpus +diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/taprio.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/taprio.json +index 12da0a939e3e5..557fb074acf0c 100644 +--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/taprio.json ++++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/taprio.json +@@ -132,6 +132,50 @@ + "echo \"1\" > /sys/bus/netdevsim/del_device" + ] + }, ++ { ++ "id": "6f62", ++ "name": "Add taprio Qdisc with too short interval", ++ "category": [ ++ "qdisc", ++ "taprio" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 8\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH root handle 1: taprio num_tc 2 queues 1@0 1@1 sched-entry S 01 300 sched-entry S 02 1700 clockid CLOCK_TAI", ++ "expExitCode": "2", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc taprio 1: root refcnt", ++ "matchCount": "0", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, ++ { ++ "id": "831f", ++ "name": "Add taprio Qdisc with too short cycle-time", ++ "category": [ ++ "qdisc", ++ "taprio" ++ ], ++ "plugins": { ++ "requires": "nsPlugin" ++ }, ++ "setup": [ ++ "echo \"1 1 8\" > /sys/bus/netdevsim/new_device" ++ ], ++ "cmdUnderTest": "$TC qdisc add dev $ETH root handle 1: taprio num_tc 2 queues 1@0 1@1 sched-entry S 01 200000 sched-entry S 02 200000 cycle-time 100 clockid CLOCK_TAI", ++ "expExitCode": "2", ++ "verifyCmd": "$TC qdisc show dev $ETH", ++ "matchPattern": "qdisc taprio 1: root refcnt", ++ "matchCount": "0", ++ "teardown": [ ++ "echo \"1\" > /sys/bus/netdevsim/del_device" ++ ] ++ }, + { + "id": "3e1e", + "name": "Add taprio Qdisc with an invalid cycle-time", |