summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2021-10-17 09:12:05 -0400
committerMike Pagano <mpagano@gentoo.org>2021-10-17 09:12:05 -0400
commit3f283992744a023735e3b1f8f39a0c9c4d16bc74 (patch)
tree2324fa39784597203e9812e04bb1110ddb4f4aaf
parentLinux patch 5.4.153 (diff)
downloadlinux-patches-3f283992744a023735e3b1f8f39a0c9c4d16bc74.tar.gz
linux-patches-3f283992744a023735e3b1f8f39a0c9c4d16bc74.tar.bz2
linux-patches-3f283992744a023735e3b1f8f39a0c9c4d16bc74.zip
Linux patch 5.4.1545.4-158
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r--0000_README4
-rw-r--r--1153_linux-5.4.154.patch948
2 files changed, 952 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 01db7036..3c15edc2 100644
--- a/0000_README
+++ b/0000_README
@@ -655,6 +655,10 @@ Patch: 1152_linux-5.4.153.patch
From: http://www.kernel.org
Desc: Linux 5.4.153
+Patch: 1153_linux-5.4.154.patch
+From: http://www.kernel.org
+Desc: Linux 5.4.154
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1153_linux-5.4.154.patch b/1153_linux-5.4.154.patch
new file mode 100644
index 00000000..dace0646
--- /dev/null
+++ b/1153_linux-5.4.154.patch
@@ -0,0 +1,948 @@
+diff --git a/Makefile b/Makefile
+index df9b1d07ca097..3358f56a37f06 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 4
+-SUBLEVEL = 153
++SUBLEVEL = 154
+ EXTRAVERSION =
+ NAME = Kleptomaniac Octopus
+
+diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
+index 05610e6924c16..f7121b775e5f0 100644
+--- a/arch/m68k/kernel/signal.c
++++ b/arch/m68k/kernel/signal.c
+@@ -448,7 +448,7 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
+
+ if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
+ fpu_version = sc->sc_fpstate[0];
+- if (CPU_IS_020_OR_030 &&
++ if (CPU_IS_020_OR_030 && !regs->stkadj &&
+ regs->vector >= (VEC_FPBRUC * 4) &&
+ regs->vector <= (VEC_FPNAN * 4)) {
+ /* Clear pending exception in 68882 idle frame */
+@@ -511,7 +511,7 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *
+ if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
+ context_size = fpstate[1];
+ fpu_version = fpstate[0];
+- if (CPU_IS_020_OR_030 &&
++ if (CPU_IS_020_OR_030 && !regs->stkadj &&
+ regs->vector >= (VEC_FPBRUC * 4) &&
+ regs->vector <= (VEC_FPNAN * 4)) {
+ /* Clear pending exception in 68882 idle frame */
+@@ -829,18 +829,24 @@ badframe:
+ return 0;
+ }
+
++static inline struct pt_regs *rte_regs(struct pt_regs *regs)
++{
++ return (void *)regs + regs->stkadj;
++}
++
+ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+ unsigned long mask)
+ {
++ struct pt_regs *tregs = rte_regs(regs);
+ sc->sc_mask = mask;
+ sc->sc_usp = rdusp();
+ sc->sc_d0 = regs->d0;
+ sc->sc_d1 = regs->d1;
+ sc->sc_a0 = regs->a0;
+ sc->sc_a1 = regs->a1;
+- sc->sc_sr = regs->sr;
+- sc->sc_pc = regs->pc;
+- sc->sc_formatvec = regs->format << 12 | regs->vector;
++ sc->sc_sr = tregs->sr;
++ sc->sc_pc = tregs->pc;
++ sc->sc_formatvec = tregs->format << 12 | tregs->vector;
+ save_a5_state(sc, regs);
+ save_fpu_state(sc, regs);
+ }
+@@ -848,6 +854,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
+ {
+ struct switch_stack *sw = (struct switch_stack *)regs - 1;
++ struct pt_regs *tregs = rte_regs(regs);
+ greg_t __user *gregs = uc->uc_mcontext.gregs;
+ int err = 0;
+
+@@ -868,9 +875,9 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
+ err |= __put_user(sw->a5, &gregs[13]);
+ err |= __put_user(sw->a6, &gregs[14]);
+ err |= __put_user(rdusp(), &gregs[15]);
+- err |= __put_user(regs->pc, &gregs[16]);
+- err |= __put_user(regs->sr, &gregs[17]);
+- err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
++ err |= __put_user(tregs->pc, &gregs[16]);
++ err |= __put_user(tregs->sr, &gregs[17]);
++ err |= __put_user((tregs->format << 12) | tregs->vector, &uc->uc_formatvec);
+ err |= rt_save_fpu_state(uc, regs);
+ return err;
+ }
+@@ -887,13 +894,14 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
+ {
+ struct sigframe __user *frame;
+- int fsize = frame_extra_sizes(regs->format);
++ struct pt_regs *tregs = rte_regs(regs);
++ int fsize = frame_extra_sizes(tregs->format);
+ struct sigcontext context;
+ int err = 0, sig = ksig->sig;
+
+ if (fsize < 0) {
+ pr_debug("setup_frame: Unknown frame format %#x\n",
+- regs->format);
++ tregs->format);
+ return -EFAULT;
+ }
+
+@@ -904,7 +912,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
+
+ err |= __put_user(sig, &frame->sig);
+
+- err |= __put_user(regs->vector, &frame->code);
++ err |= __put_user(tregs->vector, &frame->code);
+ err |= __put_user(&frame->sc, &frame->psc);
+
+ if (_NSIG_WORDS > 1)
+@@ -929,34 +937,28 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
+
+ push_cache ((unsigned long) &frame->retcode);
+
+- /*
+- * Set up registers for signal handler. All the state we are about
+- * to destroy is successfully copied to sigframe.
+- */
+- wrusp ((unsigned long) frame);
+- regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+- adjustformat(regs);
+-
+ /*
+ * This is subtle; if we build more than one sigframe, all but the
+ * first one will see frame format 0 and have fsize == 0, so we won't
+ * screw stkadj.
+ */
+- if (fsize)
++ if (fsize) {
+ regs->stkadj = fsize;
+-
+- /* Prepare to skip over the extra stuff in the exception frame. */
+- if (regs->stkadj) {
+- struct pt_regs *tregs =
+- (struct pt_regs *)((ulong)regs + regs->stkadj);
++ tregs = rte_regs(regs);
+ pr_debug("Performing stackadjust=%04lx\n", regs->stkadj);
+- /* This must be copied with decreasing addresses to
+- handle overlaps. */
+ tregs->vector = 0;
+ tregs->format = 0;
+- tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
+ }
++
++ /*
++ * Set up registers for signal handler. All the state we are about
++ * to destroy is successfully copied to sigframe.
++ */
++ wrusp ((unsigned long) frame);
++ tregs->pc = (unsigned long) ksig->ka.sa.sa_handler;
++ adjustformat(regs);
++
+ return 0;
+ }
+
+@@ -964,7 +966,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
+ {
+ struct rt_sigframe __user *frame;
+- int fsize = frame_extra_sizes(regs->format);
++ struct pt_regs *tregs = rte_regs(regs);
++ int fsize = frame_extra_sizes(tregs->format);
+ int err = 0, sig = ksig->sig;
+
+ if (fsize < 0) {
+@@ -1013,34 +1016,27 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+
+ push_cache ((unsigned long) &frame->retcode);
+
+- /*
+- * Set up registers for signal handler. All the state we are about
+- * to destroy is successfully copied to sigframe.
+- */
+- wrusp ((unsigned long) frame);
+- regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+- adjustformat(regs);
+-
+ /*
+ * This is subtle; if we build more than one sigframe, all but the
+ * first one will see frame format 0 and have fsize == 0, so we won't
+ * screw stkadj.
+ */
+- if (fsize)
++ if (fsize) {
+ regs->stkadj = fsize;
+-
+- /* Prepare to skip over the extra stuff in the exception frame. */
+- if (regs->stkadj) {
+- struct pt_regs *tregs =
+- (struct pt_regs *)((ulong)regs + regs->stkadj);
++ tregs = rte_regs(regs);
+ pr_debug("Performing stackadjust=%04lx\n", regs->stkadj);
+- /* This must be copied with decreasing addresses to
+- handle overlaps. */
+ tregs->vector = 0;
+ tregs->format = 0;
+- tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
+ }
++
++ /*
++ * Set up registers for signal handler. All the state we are about
++ * to destroy is successfully copied to sigframe.
++ */
++ wrusp ((unsigned long) frame);
++ tregs->pc = (unsigned long) ksig->ka.sa.sa_handler;
++ adjustformat(regs);
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+index f642e066e67a2..85ee0e849647e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+@@ -903,6 +903,8 @@ static int gmc_v10_0_hw_fini(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
++ gmc_v10_0_gart_disable(adev);
++
+ if (amdgpu_sriov_vf(adev)) {
+ /* full access mode, so don't touch any GMC register */
+ DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
+@@ -910,7 +912,6 @@ static int gmc_v10_0_hw_fini(void *handle)
+ }
+
+ amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
+- gmc_v10_0_gart_disable(adev);
+
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+index 688111ef814de..63205de4a5656 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+@@ -1526,6 +1526,8 @@ static int gmc_v9_0_hw_fini(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
++ gmc_v9_0_gart_disable(adev);
++
+ if (amdgpu_sriov_vf(adev)) {
+ /* full access mode, so don't touch any GMC register */
+ DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
+@@ -1534,7 +1536,6 @@ static int gmc_v9_0_hw_fini(void *handle)
+
+ amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
+ amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
+- gmc_v9_0_gart_disable(adev);
+
+ return 0;
+ }
+diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
+index 6909c045fece1..07df64daf7dae 100644
+--- a/drivers/hid/hid-apple.c
++++ b/drivers/hid/hid-apple.c
+@@ -301,12 +301,19 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field,
+
+ /*
+ * MacBook JIS keyboard has wrong logical maximum
++ * Magic Keyboard JIS has wrong logical maximum
+ */
+ static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int *rsize)
+ {
+ struct apple_sc *asc = hid_get_drvdata(hdev);
+
++ if(*rsize >=71 && rdesc[70] == 0x65 && rdesc[64] == 0x65) {
++ hid_info(hdev,
++ "fixing up Magic Keyboard JIS report descriptor\n");
++ rdesc[64] = rdesc[70] = 0xe7;
++ }
++
+ if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 &&
+ rdesc[53] == 0x65 && rdesc[59] == 0x65) {
+ hid_info(hdev,
+diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
+index d5425bc1ad61a..f6be2e70a4967 100644
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -4715,6 +4715,12 @@ static const struct wacom_features wacom_features_0x393 =
+ { "Wacom Intuos Pro S", 31920, 19950, 8191, 63,
+ INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7,
+ .touch_max = 10 };
++static const struct wacom_features wacom_features_0x3c6 =
++ { "Wacom Intuos BT S", 15200, 9500, 4095, 63,
++ INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
++static const struct wacom_features wacom_features_0x3c8 =
++ { "Wacom Intuos BT M", 21600, 13500, 4095, 63,
++ INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
+
+ static const struct wacom_features wacom_features_HID_ANY_ID =
+ { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
+@@ -4888,6 +4894,8 @@ const struct hid_device_id wacom_ids[] = {
+ { USB_DEVICE_WACOM(0x37A) },
+ { USB_DEVICE_WACOM(0x37B) },
+ { BT_DEVICE_WACOM(0x393) },
++ { BT_DEVICE_WACOM(0x3c6) },
++ { BT_DEVICE_WACOM(0x3c8) },
+ { USB_DEVICE_WACOM(0x4001) },
+ { USB_DEVICE_WACOM(0x4004) },
+ { USB_DEVICE_WACOM(0x5000) },
+diff --git a/drivers/net/ethernet/sun/Kconfig b/drivers/net/ethernet/sun/Kconfig
+index 7b982e02ea3a4..1080a2a3e13a2 100644
+--- a/drivers/net/ethernet/sun/Kconfig
++++ b/drivers/net/ethernet/sun/Kconfig
+@@ -73,6 +73,7 @@ config CASSINI
+ config SUNVNET_COMMON
+ tristate "Common routines to support Sun Virtual Networking"
+ depends on SUN_LDOMS
++ depends on INET
+ default m
+
+ config SUNVNET
+diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c
+index af8eabe7a6d44..d372626c603d4 100644
+--- a/drivers/net/phy/bcm7xxx.c
++++ b/drivers/net/phy/bcm7xxx.c
+@@ -26,7 +26,12 @@
+ #define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe
+ #define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf
+ #define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a
++#define MII_BCM7XXX_SHD_3_PCS_CTRL 0x0
++#define MII_BCM7XXX_SHD_3_PCS_STATUS 0x1
++#define MII_BCM7XXX_SHD_3_EEE_CAP 0x2
+ #define MII_BCM7XXX_SHD_3_AN_EEE_ADV 0x3
++#define MII_BCM7XXX_SHD_3_EEE_LP 0x4
++#define MII_BCM7XXX_SHD_3_EEE_WK_ERR 0x5
+ #define MII_BCM7XXX_SHD_3_PCS_CTRL_2 0x6
+ #define MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400
+ #define MII_BCM7XXX_SHD_3_AN_STAT 0xb
+@@ -210,25 +215,37 @@ static int bcm7xxx_28nm_resume(struct phy_device *phydev)
+ return genphy_config_aneg(phydev);
+ }
+
+-static int phy_set_clr_bits(struct phy_device *dev, int location,
+- int set_mask, int clr_mask)
++static int __phy_set_clr_bits(struct phy_device *dev, int location,
++ int set_mask, int clr_mask)
+ {
+ int v, ret;
+
+- v = phy_read(dev, location);
++ v = __phy_read(dev, location);
+ if (v < 0)
+ return v;
+
+ v &= ~clr_mask;
+ v |= set_mask;
+
+- ret = phy_write(dev, location, v);
++ ret = __phy_write(dev, location, v);
+ if (ret < 0)
+ return ret;
+
+ return v;
+ }
+
++static int phy_set_clr_bits(struct phy_device *dev, int location,
++ int set_mask, int clr_mask)
++{
++ int ret;
++
++ mutex_lock(&dev->mdio.bus->mdio_lock);
++ ret = __phy_set_clr_bits(dev, location, set_mask, clr_mask);
++ mutex_unlock(&dev->mdio.bus->mdio_lock);
++
++ return ret;
++}
++
+ static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
+ {
+ int ret;
+@@ -392,6 +409,93 @@ static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev)
+ return bcm7xxx_28nm_ephy_apd_enable(phydev);
+ }
+
++#define MII_BCM7XXX_REG_INVALID 0xff
++
++static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum)
++{
++ switch (regnum) {
++ case MDIO_CTRL1:
++ return MII_BCM7XXX_SHD_3_PCS_CTRL;
++ case MDIO_STAT1:
++ return MII_BCM7XXX_SHD_3_PCS_STATUS;
++ case MDIO_PCS_EEE_ABLE:
++ return MII_BCM7XXX_SHD_3_EEE_CAP;
++ case MDIO_AN_EEE_ADV:
++ return MII_BCM7XXX_SHD_3_AN_EEE_ADV;
++ case MDIO_AN_EEE_LPABLE:
++ return MII_BCM7XXX_SHD_3_EEE_LP;
++ case MDIO_PCS_EEE_WK_ERR:
++ return MII_BCM7XXX_SHD_3_EEE_WK_ERR;
++ default:
++ return MII_BCM7XXX_REG_INVALID;
++ }
++}
++
++static bool bcm7xxx_28nm_ephy_dev_valid(int devnum)
++{
++ return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS;
++}
++
++static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev,
++ int devnum, u16 regnum)
++{
++ u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
++ int ret;
++
++ if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
++ shd == MII_BCM7XXX_REG_INVALID)
++ return -EOPNOTSUPP;
++
++ /* set shadow mode 2 */
++ ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
++ MII_BCM7XXX_SHD_MODE_2, 0);
++ if (ret < 0)
++ return ret;
++
++ /* Access the desired shadow register address */
++ ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
++ if (ret < 0)
++ goto reset_shadow_mode;
++
++ ret = __phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT);
++
++reset_shadow_mode:
++ /* reset shadow mode 2 */
++ __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
++ MII_BCM7XXX_SHD_MODE_2);
++ return ret;
++}
++
++static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev,
++ int devnum, u16 regnum, u16 val)
++{
++ u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
++ int ret;
++
++ if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
++ shd == MII_BCM7XXX_REG_INVALID)
++ return -EOPNOTSUPP;
++
++ /* set shadow mode 2 */
++ ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
++ MII_BCM7XXX_SHD_MODE_2, 0);
++ if (ret < 0)
++ return ret;
++
++ /* Access the desired shadow register address */
++ ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
++ if (ret < 0)
++ goto reset_shadow_mode;
++
++ /* Write the desired value in the shadow register */
++ __phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
++
++reset_shadow_mode:
++ /* reset shadow mode 2 */
++ return __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
++ MII_BCM7XXX_SHD_MODE_2);
++}
++
+ static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
+ {
+ int ret;
+@@ -563,6 +667,8 @@ static int bcm7xxx_28nm_probe(struct phy_device *phydev)
+ .get_strings = bcm_phy_get_strings, \
+ .get_stats = bcm7xxx_28nm_get_phy_stats, \
+ .probe = bcm7xxx_28nm_probe, \
++ .read_mmd = bcm7xxx_28nm_ephy_read_mmd, \
++ .write_mmd = bcm7xxx_28nm_ephy_write_mmd, \
+ }
+
+ #define BCM7XXX_40NM_EPHY(_oui, _name) \
+diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
+index 43e682297fd5f..0a1734f34587d 100644
+--- a/drivers/scsi/ses.c
++++ b/drivers/scsi/ses.c
+@@ -118,7 +118,7 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code,
+ static int ses_send_diag(struct scsi_device *sdev, int page_code,
+ void *buf, int bufflen)
+ {
+- u32 result;
++ int result;
+
+ unsigned char cmd[] = {
+ SEND_DIAGNOSTIC,
+diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
+index bfec84aacd90b..cb833c5fb9ce2 100644
+--- a/drivers/scsi/virtio_scsi.c
++++ b/drivers/scsi/virtio_scsi.c
+@@ -297,7 +297,7 @@ static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
+ }
+ break;
+ default:
+- pr_info("Unsupport virtio scsi event reason %x\n", event->reason);
++ pr_info("Unsupported virtio scsi event reason %x\n", event->reason);
+ }
+ }
+
+@@ -381,7 +381,7 @@ static void virtscsi_handle_event(struct work_struct *work)
+ virtscsi_handle_param_change(vscsi, event);
+ break;
+ default:
+- pr_err("Unsupport virtio scsi event %x\n", event->event);
++ pr_err("Unsupported virtio scsi event %x\n", event->event);
+ }
+ virtscsi_kick_event(vscsi, event_node);
+ }
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 46151bda62368..cdb10e9fded65 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -733,18 +733,13 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ void *kaddr;
+ struct ext4_iloc iloc;
+
+- if (unlikely(copied < len)) {
+- if (!PageUptodate(page)) {
+- copied = 0;
+- goto out;
+- }
+- }
++ if (unlikely(copied < len) && !PageUptodate(page))
++ return 0;
+
+ ret = ext4_get_inode_loc(inode, &iloc);
+ if (ret) {
+ ext4_std_error(inode->i_sb, ret);
+- copied = 0;
+- goto out;
++ return ret;
+ }
+
+ ext4_write_lock_xattr(inode, &no_expand);
+@@ -757,7 +752,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ (void) ext4_find_inline_data_nolock(inode);
+
+ kaddr = kmap_atomic(page);
+- ext4_write_inline_data(inode, &iloc, kaddr, pos, len);
++ ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
+ kunmap_atomic(kaddr);
+ SetPageUptodate(page);
+ /* clear page dirty so that writepages wouldn't work for us. */
+@@ -766,7 +761,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
+ ext4_write_unlock_xattr(inode, &no_expand);
+ brelse(iloc.bh);
+ mark_inode_dirty(inode);
+-out:
++
+ return copied;
+ }
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 48b467353f6f1..dcbd8ac8d4711 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1439,6 +1439,7 @@ static int ext4_write_end(struct file *file,
+ goto errout;
+ }
+ copied = ret;
++ ret = 0;
+ } else
+ copied = block_write_end(file, mapping, pos,
+ len, copied, page, fsdata);
+@@ -1465,13 +1466,14 @@ static int ext4_write_end(struct file *file,
+ if (i_size_changed || inline_data)
+ ext4_mark_inode_dirty(handle, inode);
+
++errout:
+ if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
+ /* if we have allocated more blocks and copied
+ * less. We will have blocks allocated outside
+ * inode->i_size. So truncate them
+ */
+ ext4_orphan_add(handle, inode);
+-errout:
++
+ ret2 = ext4_journal_stop(handle);
+ if (!ret)
+ ret = ret2;
+@@ -1554,6 +1556,7 @@ static int ext4_journalled_write_end(struct file *file,
+ goto errout;
+ }
+ copied = ret;
++ ret = 0;
+ } else if (unlikely(copied < len) && !PageUptodate(page)) {
+ copied = 0;
+ ext4_journalled_zero_new_buffers(handle, page, from, to);
+@@ -1583,6 +1586,7 @@ static int ext4_journalled_write_end(struct file *file,
+ ret = ret2;
+ }
+
++errout:
+ if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
+ /* if we have allocated more blocks and copied
+ * less. We will have blocks allocated outside
+@@ -1590,7 +1594,6 @@ static int ext4_journalled_write_end(struct file *file,
+ */
+ ext4_orphan_add(handle, inode);
+
+-errout:
+ ret2 = ext4_journal_stop(handle);
+ if (!ret)
+ ret = ret2;
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 5710b80f8050a..afee5d5eb9458 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -1500,7 +1500,7 @@ extern struct pid *cad_pid;
+ #define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
+ #define used_math() tsk_used_math(current)
+
+-static inline bool is_percpu_thread(void)
++static __always_inline bool is_percpu_thread(void)
+ {
+ #ifdef CONFIG_SMP
+ return (current->flags & PF_NO_SETAFFINITY) &&
+diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
+index b16f9236de147..d1585b54fb0bd 100644
+--- a/include/net/pkt_sched.h
++++ b/include/net/pkt_sched.h
+@@ -11,6 +11,7 @@
+ #include <uapi/linux/pkt_sched.h>
+
+ #define DEFAULT_TX_QUEUE_LEN 1000
++#define STAB_SIZE_LOG_MAX 30
+
+ struct qdisc_walker {
+ int stop;
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+index 8bb543b0e775e..41268612bdd4e 100644
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -273,6 +273,7 @@ ip6t_do_table(struct sk_buff *skb,
+ * things we don't know, ie. tcp syn flag or ports). If the
+ * rule is also a fragment-specific rule, non-fragments won't
+ * match it. */
++ acpar.fragoff = 0;
+ acpar.hotdrop = false;
+ acpar.state = state;
+
+diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
+index 1708b64d41094..d7ae7415d54d0 100644
+--- a/net/mac80211/mesh_pathtbl.c
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -60,7 +60,10 @@ static struct mesh_table *mesh_table_alloc(void)
+ atomic_set(&newtbl->entries, 0);
+ spin_lock_init(&newtbl->gates_lock);
+ spin_lock_init(&newtbl->walk_lock);
+- rhashtable_init(&newtbl->rhead, &mesh_rht_params);
++ if (rhashtable_init(&newtbl->rhead, &mesh_rht_params)) {
++ kfree(newtbl);
++ return NULL;
++ }
+
+ return newtbl;
+ }
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 670d84e54db73..c7e6bf7c22c78 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3952,7 +3952,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
+ if (!bssid)
+ return false;
+ if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
+- ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
++ ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2) ||
++ !is_valid_ether_addr(hdr->addr2))
+ return false;
+ if (ieee80211_is_beacon(hdr->frame_control))
+ return true;
+diff --git a/net/netfilter/nf_nat_masquerade.c b/net/netfilter/nf_nat_masquerade.c
+index 8e8a65d46345b..acd73f717a088 100644
+--- a/net/netfilter/nf_nat_masquerade.c
++++ b/net/netfilter/nf_nat_masquerade.c
+@@ -9,8 +9,19 @@
+
+ #include <net/netfilter/nf_nat_masquerade.h>
+
++struct masq_dev_work {
++ struct work_struct work;
++ struct net *net;
++ union nf_inet_addr addr;
++ int ifindex;
++ int (*iter)(struct nf_conn *i, void *data);
++};
++
++#define MAX_MASQ_WORKER_COUNT 16
++
+ static DEFINE_MUTEX(masq_mutex);
+ static unsigned int masq_refcnt __read_mostly;
++static atomic_t masq_worker_count __read_mostly;
+
+ unsigned int
+ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
+@@ -63,13 +74,71 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
+ }
+ EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4);
+
+-static int device_cmp(struct nf_conn *i, void *ifindex)
++static void iterate_cleanup_work(struct work_struct *work)
++{
++ struct masq_dev_work *w;
++
++ w = container_of(work, struct masq_dev_work, work);
++
++ nf_ct_iterate_cleanup_net(w->net, w->iter, (void *)w, 0, 0);
++
++ put_net(w->net);
++ kfree(w);
++ atomic_dec(&masq_worker_count);
++ module_put(THIS_MODULE);
++}
++
++/* Iterate conntrack table in the background and remove conntrack entries
++ * that use the device/address being removed.
++ *
++ * In case too many work items have been queued already or memory allocation
++ * fails iteration is skipped, conntrack entries will time out eventually.
++ */
++static void nf_nat_masq_schedule(struct net *net, union nf_inet_addr *addr,
++ int ifindex,
++ int (*iter)(struct nf_conn *i, void *data),
++ gfp_t gfp_flags)
++{
++ struct masq_dev_work *w;
++
++ if (atomic_read(&masq_worker_count) > MAX_MASQ_WORKER_COUNT)
++ return;
++
++ net = maybe_get_net(net);
++ if (!net)
++ return;
++
++ if (!try_module_get(THIS_MODULE))
++ goto err_module;
++
++ w = kzalloc(sizeof(*w), gfp_flags);
++ if (w) {
++ /* We can overshoot MAX_MASQ_WORKER_COUNT, no big deal */
++ atomic_inc(&masq_worker_count);
++
++ INIT_WORK(&w->work, iterate_cleanup_work);
++ w->ifindex = ifindex;
++ w->net = net;
++ w->iter = iter;
++ if (addr)
++ w->addr = *addr;
++ schedule_work(&w->work);
++ return;
++ }
++
++ module_put(THIS_MODULE);
++ err_module:
++ put_net(net);
++}
++
++static int device_cmp(struct nf_conn *i, void *arg)
+ {
+ const struct nf_conn_nat *nat = nfct_nat(i);
++ const struct masq_dev_work *w = arg;
+
+ if (!nat)
+ return 0;
+- return nat->masq_index == (int)(long)ifindex;
++ return nat->masq_index == w->ifindex;
+ }
+
+ static int masq_device_event(struct notifier_block *this,
+@@ -85,8 +154,8 @@ static int masq_device_event(struct notifier_block *this,
+ * and forget them.
+ */
+
+- nf_ct_iterate_cleanup_net(net, device_cmp,
+- (void *)(long)dev->ifindex, 0, 0);
++ nf_nat_masq_schedule(net, NULL, dev->ifindex,
++ device_cmp, GFP_KERNEL);
+ }
+
+ return NOTIFY_DONE;
+@@ -94,35 +163,45 @@ static int masq_device_event(struct notifier_block *this,
+
+ static int inet_cmp(struct nf_conn *ct, void *ptr)
+ {
+- struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+- struct net_device *dev = ifa->ifa_dev->dev;
+ struct nf_conntrack_tuple *tuple;
++ struct masq_dev_work *w = ptr;
+
+- if (!device_cmp(ct, (void *)(long)dev->ifindex))
++ if (!device_cmp(ct, ptr))
+ return 0;
+
+ tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+
+- return ifa->ifa_address == tuple->dst.u3.ip;
++ return nf_inet_addr_cmp(&w->addr, &tuple->dst.u3);
+ }
+
+ static int masq_inet_event(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+ {
+- struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev;
+- struct net *net = dev_net(idev->dev);
++ const struct in_ifaddr *ifa = ptr;
++ const struct in_device *idev;
++ const struct net_device *dev;
++ union nf_inet_addr addr;
++
++ if (event != NETDEV_DOWN)
++ return NOTIFY_DONE;
+
+ /* The masq_dev_notifier will catch the case of the device going
+ * down. So if the inetdev is dead and being destroyed we have
+ * no work to do. Otherwise this is an individual address removal
+ * and we have to perform the flush.
+ */
++ idev = ifa->ifa_dev;
+ if (idev->dead)
+ return NOTIFY_DONE;
+
+- if (event == NETDEV_DOWN)
+- nf_ct_iterate_cleanup_net(net, inet_cmp, ptr, 0, 0);
++ memset(&addr, 0, sizeof(addr));
++
++ addr.ip = ifa->ifa_address;
++
++ dev = idev->dev;
++ nf_nat_masq_schedule(dev_net(idev->dev), &addr, dev->ifindex,
++ inet_cmp, GFP_KERNEL);
+
+ return NOTIFY_DONE;
+ }
+@@ -136,8 +215,6 @@ static struct notifier_block masq_inet_notifier = {
+ };
+
+ #if IS_ENABLED(CONFIG_IPV6)
+-static atomic_t v6_worker_count __read_mostly;
+-
+ static int
+ nat_ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
+ const struct in6_addr *daddr, unsigned int srcprefs,
+@@ -187,40 +264,6 @@ nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
+ }
+ EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6);
+
+-struct masq_dev_work {
+- struct work_struct work;
+- struct net *net;
+- struct in6_addr addr;
+- int ifindex;
+-};
+-
+-static int inet6_cmp(struct nf_conn *ct, void *work)
+-{
+- struct masq_dev_work *w = (struct masq_dev_work *)work;
+- struct nf_conntrack_tuple *tuple;
+-
+- if (!device_cmp(ct, (void *)(long)w->ifindex))
+- return 0;
+-
+- tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+-
+- return ipv6_addr_equal(&w->addr, &tuple->dst.u3.in6);
+-}
+-
+-static void iterate_cleanup_work(struct work_struct *work)
+-{
+- struct masq_dev_work *w;
+-
+- w = container_of(work, struct masq_dev_work, work);
+-
+- nf_ct_iterate_cleanup_net(w->net, inet6_cmp, (void *)w, 0, 0);
+-
+- put_net(w->net);
+- kfree(w);
+- atomic_dec(&v6_worker_count);
+- module_put(THIS_MODULE);
+-}
+-
+ /* atomic notifier; can't call nf_ct_iterate_cleanup_net (it can sleep).
+ *
+ * Defer it to the system workqueue.
+@@ -233,36 +276,19 @@ static int masq_inet6_event(struct notifier_block *this,
+ {
+ struct inet6_ifaddr *ifa = ptr;
+ const struct net_device *dev;
+- struct masq_dev_work *w;
+- struct net *net;
++ union nf_inet_addr addr;
+
+- if (event != NETDEV_DOWN || atomic_read(&v6_worker_count) >= 16)
++ if (event != NETDEV_DOWN)
+ return NOTIFY_DONE;
+
+ dev = ifa->idev->dev;
+- net = maybe_get_net(dev_net(dev));
+- if (!net)
+- return NOTIFY_DONE;
+
+- if (!try_module_get(THIS_MODULE))
+- goto err_module;
++ memset(&addr, 0, sizeof(addr));
+
+- w = kmalloc(sizeof(*w), GFP_ATOMIC);
+- if (w) {
+- atomic_inc(&v6_worker_count);
+-
+- INIT_WORK(&w->work, iterate_cleanup_work);
+- w->ifindex = dev->ifindex;
+- w->net = net;
+- w->addr = ifa->addr;
+- schedule_work(&w->work);
++ addr.in6 = ifa->addr;
+
+- return NOTIFY_DONE;
+- }
+-
+- module_put(THIS_MODULE);
+- err_module:
+- put_net(net);
++ nf_nat_masq_schedule(dev_net(dev), &addr, dev->ifindex, inet_cmp,
++ GFP_ATOMIC);
+ return NOTIFY_DONE;
+ }
+
+diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
+index 3b1b5ee521379..e70f990334083 100644
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -510,6 +510,12 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt,
+ return stab;
+ }
+
++ if (s->size_log > STAB_SIZE_LOG_MAX ||
++ s->cell_log > STAB_SIZE_LOG_MAX) {
++ NL_SET_ERR_MSG(extack, "Invalid logarithmic size of size table");
++ return ERR_PTR(-EINVAL);
++ }
++
+ stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL);
+ if (!stab)
+ return ERR_PTR(-ENOMEM);