diff options
author | Mike Pagano <mpagano@gentoo.org> | 2019-09-21 11:53:16 -0400 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2019-09-21 11:53:16 -0400 |
commit | bdd00b553c1319822d9f07df86de47f812b2fbea (patch) | |
tree | 2f78f426c963fbf2aa9efdfe405b95cbc9e7090e | |
parent | Kernel patch enables gcc >= v9.1 optimizations for additional CPUs. (diff) | |
download | linux-patches-5.3-3.tar.gz linux-patches-5.3-3.tar.bz2 linux-patches-5.3-3.zip |
Linux patch 5.3.15.3-3
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1000_linux-5.3.1.patch | 1081 |
2 files changed, 1085 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 4403e5a9..f9d1f158 100644 --- a/0000_README +++ b/0000_README @@ -43,6 +43,10 @@ EXPERIMENTAL Individual Patch Descriptions: -------------------------------------------------------------------------- +Patch: 1000_linux-5.3.1.patch +From: http://www.kernel.org +Desc: Linux 5.3.1 + 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/1000_linux-5.3.1.patch b/1000_linux-5.3.1.patch new file mode 100644 index 00000000..7d865ae2 --- /dev/null +++ b/1000_linux-5.3.1.patch @@ -0,0 +1,1081 @@ +diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt +index 1da2f1668f08..845d689e0fd7 100644 +--- a/Documentation/filesystems/overlayfs.txt ++++ b/Documentation/filesystems/overlayfs.txt +@@ -302,7 +302,7 @@ beneath or above the path of another overlay lower layer path. + + Using an upper layer path and/or a workdir path that are already used by + another overlay mount is not allowed and may fail with EBUSY. Using +-partially overlapping paths is not allowed but will not fail with EBUSY. ++partially overlapping paths is not allowed and may fail with EBUSY. + If files are accessed from two overlayfs mounts which share or overlap the + upper layer and/or workdir path the behavior of the overlay is undefined, + though it will not result in a crash or deadlock. +diff --git a/Documentation/sphinx/automarkup.py b/Documentation/sphinx/automarkup.py +index 77e89c1956d7..a8798369e8f7 100644 +--- a/Documentation/sphinx/automarkup.py ++++ b/Documentation/sphinx/automarkup.py +@@ -25,7 +25,7 @@ RE_function = re.compile(r'([\w_][\w\d_]+\(\))') + # to the creation of incorrect and confusing cross references. So + # just don't even try with these names. + # +-Skipfuncs = [ 'open', 'close', 'read', 'write', 'fcntl', 'mmap' ++Skipfuncs = [ 'open', 'close', 'read', 'write', 'fcntl', 'mmap', + 'select', 'poll', 'fork', 'execve', 'clone', 'ioctl'] + + # +diff --git a/Makefile b/Makefile +index 6886f22902c9..f32e8d2e09c3 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 3 +-SUBLEVEL = 0 ++SUBLEVEL = 1 + EXTRAVERSION = + NAME = Bobtail Squid + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index e09760ece844..8eb5c0fbdee6 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -220,8 +220,10 @@ static inline void set_pte(pte_t *ptep, pte_t pte) + * Only if the new pte is valid and kernel, otherwise TLB maintenance + * or update_mmu_cache() have the necessary barriers. + */ +- if (pte_valid_not_user(pte)) ++ if (pte_valid_not_user(pte)) { + dsb(ishst); ++ isb(); ++ } + } + + extern void __sync_icache_dcache(pte_t pteval); +@@ -484,8 +486,10 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) + + WRITE_ONCE(*pmdp, pmd); + +- if (pmd_valid(pmd)) ++ if (pmd_valid(pmd)) { + dsb(ishst); ++ isb(); ++ } + } + + static inline void pmd_clear(pmd_t *pmdp) +@@ -543,8 +547,10 @@ static inline void set_pud(pud_t *pudp, pud_t pud) + + WRITE_ONCE(*pudp, pud); + +- if (pud_valid(pud)) ++ if (pud_valid(pud)) { + dsb(ishst); ++ isb(); ++ } + } + + static inline void pud_clear(pud_t *pudp) +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 0469aceaa230..485865fd0412 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -3780,7 +3780,7 @@ static int compat_getdrvprm(int drive, + v.native_format = UDP->native_format; + mutex_unlock(&floppy_mutex); + +- if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params))) ++ if (copy_to_user(arg, &v, sizeof(struct compat_floppy_drive_params))) + return -EFAULT; + return 0; + } +@@ -3816,7 +3816,7 @@ static int compat_getdrvstat(int drive, bool poll, + v.bufblocks = UDRS->bufblocks; + mutex_unlock(&floppy_mutex); + +- if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) ++ if (copy_to_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) + return -EFAULT; + return 0; + Eintr: +diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c +index 0739f3b70347..db0812263d46 100644 +--- a/drivers/firmware/google/vpd.c ++++ b/drivers/firmware/google/vpd.c +@@ -92,8 +92,8 @@ static int vpd_section_check_key_name(const u8 *key, s32 key_len) + return VPD_OK; + } + +-static int vpd_section_attrib_add(const u8 *key, s32 key_len, +- const u8 *value, s32 value_len, ++static int vpd_section_attrib_add(const u8 *key, u32 key_len, ++ const u8 *value, u32 value_len, + void *arg) + { + int ret; +diff --git a/drivers/firmware/google/vpd_decode.c b/drivers/firmware/google/vpd_decode.c +index 92e3258552fc..dda525c0f968 100644 +--- a/drivers/firmware/google/vpd_decode.c ++++ b/drivers/firmware/google/vpd_decode.c +@@ -9,8 +9,8 @@ + + #include "vpd_decode.h" + +-static int vpd_decode_len(const s32 max_len, const u8 *in, +- s32 *length, s32 *decoded_len) ++static int vpd_decode_len(const u32 max_len, const u8 *in, ++ u32 *length, u32 *decoded_len) + { + u8 more; + int i = 0; +@@ -30,18 +30,39 @@ static int vpd_decode_len(const s32 max_len, const u8 *in, + } while (more); + + *decoded_len = i; ++ return VPD_OK; ++} ++ ++static int vpd_decode_entry(const u32 max_len, const u8 *input_buf, ++ u32 *_consumed, const u8 **entry, u32 *entry_len) ++{ ++ u32 decoded_len; ++ u32 consumed = *_consumed; ++ ++ if (vpd_decode_len(max_len - consumed, &input_buf[consumed], ++ entry_len, &decoded_len) != VPD_OK) ++ return VPD_FAIL; ++ if (max_len - consumed < decoded_len) ++ return VPD_FAIL; ++ ++ consumed += decoded_len; ++ *entry = input_buf + consumed; ++ ++ /* entry_len is untrusted data and must be checked again. */ ++ if (max_len - consumed < *entry_len) ++ return VPD_FAIL; + ++ consumed += decoded_len; ++ *_consumed = consumed; + return VPD_OK; + } + +-int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed, ++int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed, + vpd_decode_callback callback, void *callback_arg) + { + int type; +- int res; +- s32 key_len; +- s32 value_len; +- s32 decoded_len; ++ u32 key_len; ++ u32 value_len; + const u8 *key; + const u8 *value; + +@@ -56,26 +77,14 @@ int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed, + case VPD_TYPE_STRING: + (*consumed)++; + +- /* key */ +- res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed], +- &key_len, &decoded_len); +- if (res != VPD_OK || *consumed + decoded_len >= max_len) ++ if (vpd_decode_entry(max_len, input_buf, consumed, &key, ++ &key_len) != VPD_OK) + return VPD_FAIL; + +- *consumed += decoded_len; +- key = &input_buf[*consumed]; +- *consumed += key_len; +- +- /* value */ +- res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed], +- &value_len, &decoded_len); +- if (res != VPD_OK || *consumed + decoded_len > max_len) ++ if (vpd_decode_entry(max_len, input_buf, consumed, &value, ++ &value_len) != VPD_OK) + return VPD_FAIL; + +- *consumed += decoded_len; +- value = &input_buf[*consumed]; +- *consumed += value_len; +- + if (type == VPD_TYPE_STRING) + return callback(key, key_len, value, value_len, + callback_arg); +diff --git a/drivers/firmware/google/vpd_decode.h b/drivers/firmware/google/vpd_decode.h +index cf8c2ace155a..8dbe41cac599 100644 +--- a/drivers/firmware/google/vpd_decode.h ++++ b/drivers/firmware/google/vpd_decode.h +@@ -25,8 +25,8 @@ enum { + }; + + /* Callback for vpd_decode_string to invoke. */ +-typedef int vpd_decode_callback(const u8 *key, s32 key_len, +- const u8 *value, s32 value_len, ++typedef int vpd_decode_callback(const u8 *key, u32 key_len, ++ const u8 *value, u32 value_len, + void *arg); + + /* +@@ -44,7 +44,7 @@ typedef int vpd_decode_callback(const u8 *key, s32 key_len, + * If one entry is successfully decoded, sends it to callback and returns the + * result. + */ +-int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed, ++int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed, + vpd_decode_callback callback, void *callback_arg); + + #endif /* __VPD_DECODE_H */ +diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c +index c659e18b358b..676d233d46d5 100644 +--- a/drivers/media/usb/dvb-usb/technisat-usb2.c ++++ b/drivers/media/usb/dvb-usb/technisat-usb2.c +@@ -608,10 +608,9 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) + static int technisat_usb2_get_ir(struct dvb_usb_device *d) + { + struct technisat_usb2_state *state = d->priv; +- u8 *buf = state->buf; +- u8 *b; +- int ret; + struct ir_raw_event ev; ++ u8 *buf = state->buf; ++ int i, ret; + + buf[0] = GET_IR_DATA_VENDOR_REQUEST; + buf[1] = 0x08; +@@ -647,26 +646,25 @@ unlock: + return 0; /* no key pressed */ + + /* decoding */ +- b = buf+1; + + #if 0 + deb_rc("RC: %d ", ret); +- debug_dump(b, ret, deb_rc); ++ debug_dump(buf + 1, ret, deb_rc); + #endif + + ev.pulse = 0; +- while (1) { +- ev.pulse = !ev.pulse; +- ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000; +- ir_raw_event_store(d->rc_dev, &ev); +- +- b++; +- if (*b == 0xff) { ++ for (i = 1; i < ARRAY_SIZE(state->buf); i++) { ++ if (buf[i] == 0xff) { + ev.pulse = 0; + ev.duration = 888888*2; + ir_raw_event_store(d->rc_dev, &ev); + break; + } ++ ++ ev.pulse = !ev.pulse; ++ ev.duration = (buf[i] * FIRMWARE_CLOCK_DIVISOR * ++ FIRMWARE_CLOCK_TICK) / 1000; ++ ir_raw_event_store(d->rc_dev, &ev); + } + + ir_raw_event_handle(d->rc_dev); +diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c +index e4d2dcd5cc0f..19c90fa9e443 100644 +--- a/drivers/media/usb/tm6000/tm6000-dvb.c ++++ b/drivers/media/usb/tm6000/tm6000-dvb.c +@@ -97,6 +97,7 @@ static void tm6000_urb_received(struct urb *urb) + printk(KERN_ERR "tm6000: error %s\n", __func__); + kfree(urb->transfer_buffer); + usb_free_urb(urb); ++ dev->dvb->bulk_urb = NULL; + } + } + } +@@ -127,6 +128,7 @@ static int tm6000_start_stream(struct tm6000_core *dev) + dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); + if (!dvb->bulk_urb->transfer_buffer) { + usb_free_urb(dvb->bulk_urb); ++ dvb->bulk_urb = NULL; + return -ENOMEM; + } + +@@ -153,6 +155,7 @@ static int tm6000_start_stream(struct tm6000_core *dev) + + kfree(dvb->bulk_urb->transfer_buffer); + usb_free_urb(dvb->bulk_urb); ++ dvb->bulk_urb = NULL; + return ret; + } + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index fd54c7c87485..b19ab09cb18f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -4451,10 +4451,12 @@ int stmmac_suspend(struct device *dev) + if (!ndev || !netif_running(ndev)) + return 0; + +- phylink_stop(priv->phylink); +- + mutex_lock(&priv->lock); + ++ rtnl_lock(); ++ phylink_stop(priv->phylink); ++ rtnl_unlock(); ++ + netif_device_detach(ndev); + stmmac_stop_all_queues(priv); + +@@ -4558,9 +4560,11 @@ int stmmac_resume(struct device *dev) + + stmmac_start_all_queues(priv); + +- mutex_unlock(&priv->lock); +- ++ rtnl_lock(); + phylink_start(priv->phylink); ++ rtnl_unlock(); ++ ++ mutex_unlock(&priv->lock); + + return 0; + } +diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c +index 8d33970a2950..5f5722bf6762 100644 +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -906,7 +906,7 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue, + __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); + } + if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) { +- queue->rx.rsp_cons = ++cons; ++ queue->rx.rsp_cons = ++cons + skb_queue_len(list); + kfree_skb(nskb); + return ~0U; + } +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c +index 34ff6434da8f..6bb49cc25c63 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp.c +@@ -35,7 +35,7 @@ + #define PLL_READY_GATE_EN BIT(3) + /* QPHY_PCS_STATUS bit */ + #define PHYSTATUS BIT(6) +-/* QPHY_COM_PCS_READY_STATUS bit */ ++/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ + #define PCS_READY BIT(0) + + /* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ +@@ -115,6 +115,7 @@ enum qphy_reg_layout { + QPHY_SW_RESET, + QPHY_START_CTRL, + QPHY_PCS_READY_STATUS, ++ QPHY_PCS_STATUS, + QPHY_PCS_AUTONOMOUS_MODE_CTRL, + QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, + QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, +@@ -133,7 +134,7 @@ static const unsigned int pciephy_regs_layout[] = { + [QPHY_FLL_MAN_CODE] = 0xd4, + [QPHY_SW_RESET] = 0x00, + [QPHY_START_CTRL] = 0x08, +- [QPHY_PCS_READY_STATUS] = 0x174, ++ [QPHY_PCS_STATUS] = 0x174, + }; + + static const unsigned int usb3phy_regs_layout[] = { +@@ -144,7 +145,7 @@ static const unsigned int usb3phy_regs_layout[] = { + [QPHY_FLL_MAN_CODE] = 0xd0, + [QPHY_SW_RESET] = 0x00, + [QPHY_START_CTRL] = 0x08, +- [QPHY_PCS_READY_STATUS] = 0x17c, ++ [QPHY_PCS_STATUS] = 0x17c, + [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, + [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, + [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, +@@ -153,7 +154,7 @@ static const unsigned int usb3phy_regs_layout[] = { + static const unsigned int qmp_v3_usb3phy_regs_layout[] = { + [QPHY_SW_RESET] = 0x00, + [QPHY_START_CTRL] = 0x08, +- [QPHY_PCS_READY_STATUS] = 0x174, ++ [QPHY_PCS_STATUS] = 0x174, + [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, + [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, + [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, +@@ -911,7 +912,6 @@ struct qmp_phy_cfg { + + unsigned int start_ctrl; + unsigned int pwrdn_ctrl; +- unsigned int mask_pcs_ready; + unsigned int mask_com_pcs_ready; + + /* true, if PHY has a separate PHY_COM control block */ +@@ -1074,7 +1074,6 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = { + + .start_ctrl = PCS_START | PLL_READY_GATE_EN, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, +- .mask_pcs_ready = PHYSTATUS, + .mask_com_pcs_ready = PCS_READY, + + .has_phy_com_ctrl = true, +@@ -1106,7 +1105,6 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, +- .mask_pcs_ready = PHYSTATUS, + }; + + /* list of resets */ +@@ -1136,7 +1134,6 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, +- .mask_pcs_ready = PHYSTATUS, + + .has_phy_com_ctrl = false, + .has_lane_rst = false, +@@ -1167,7 +1164,6 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, +- .mask_pcs_ready = PHYSTATUS, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +@@ -1199,7 +1195,6 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, +- .mask_pcs_ready = PHYSTATUS, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +@@ -1226,7 +1221,6 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { + + .start_ctrl = SERDES_START, + .pwrdn_ctrl = SW_PWRDN, +- .mask_pcs_ready = PCS_READY, + + .is_dual_lane_phy = true, + .no_pcs_sw_reset = true, +@@ -1254,7 +1248,6 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, +- .mask_pcs_ready = PHYSTATUS, + }; + + static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { +@@ -1279,7 +1272,6 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, +- .mask_pcs_ready = PHYSTATUS, + + .is_dual_lane_phy = true, + }; +@@ -1457,7 +1449,7 @@ static int qcom_qmp_phy_enable(struct phy *phy) + void __iomem *pcs = qphy->pcs; + void __iomem *dp_com = qmp->dp_com; + void __iomem *status; +- unsigned int mask, val; ++ unsigned int mask, val, ready; + int ret; + + dev_vdbg(qmp->dev, "Initializing QMP phy\n"); +@@ -1545,10 +1537,17 @@ static int qcom_qmp_phy_enable(struct phy *phy) + /* start SerDes and Phy-Coding-Sublayer */ + qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); + +- status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; +- mask = cfg->mask_pcs_ready; ++ if (cfg->type == PHY_TYPE_UFS) { ++ status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; ++ mask = PCS_READY; ++ ready = PCS_READY; ++ } else { ++ status = pcs + cfg->regs[QPHY_PCS_STATUS]; ++ mask = PHYSTATUS; ++ ready = 0; ++ } + +- ret = readl_poll_timeout(status, val, val & mask, 10, ++ ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, + PHY_INIT_COMPLETE_TIMEOUT); + if (ret) { + dev_err(qmp->dev, "phy initialization timed-out\n"); +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 8ffba67568ec..b7f6b1324395 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -61,6 +61,7 @@ + USB2_OBINT_IDDIGCHG) + + /* VBCTRL */ ++#define USB2_VBCTRL_OCCLREN BIT(16) + #define USB2_VBCTRL_DRVVBUSSEL BIT(8) + + /* LINECTRL1 */ +@@ -374,6 +375,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) + writel(val, usb2_base + USB2_LINECTRL1); + + val = readl(usb2_base + USB2_VBCTRL); ++ val &= ~USB2_VBCTRL_OCCLREN; + writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); + val = readl(usb2_base + USB2_ADPCTRL); + writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index 0b4f36905321..8e667967928a 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -1400,7 +1400,6 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending) + + atmel_port->hd_start_rx = false; + atmel_start_rx(port); +- return; + } + + atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx); +diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c +index 73d71a4e6c0c..f49b7d6fbc88 100644 +--- a/drivers/tty/serial/sprd_serial.c ++++ b/drivers/tty/serial/sprd_serial.c +@@ -609,7 +609,7 @@ static inline void sprd_rx(struct uart_port *port) + + if (lsr & (SPRD_LSR_BI | SPRD_LSR_PE | + SPRD_LSR_FE | SPRD_LSR_OE)) +- if (handle_lsr_errors(port, &lsr, &flag)) ++ if (handle_lsr_errors(port, &flag, &lsr)) + continue; + if (uart_handle_sysrq_char(port, ch)) + continue; +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index 9d6cb709ca7b..151a74a54386 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -921,7 +921,7 @@ int usb_get_bos_descriptor(struct usb_device *dev) + struct usb_bos_descriptor *bos; + struct usb_dev_cap_header *cap; + struct usb_ssp_cap_descriptor *ssp_cap; +- unsigned char *buffer; ++ unsigned char *buffer, *buffer0; + int length, total_len, num, i, ssac; + __u8 cap_type; + int ret; +@@ -966,10 +966,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) + ret = -ENOMSG; + goto err; + } ++ ++ buffer0 = buffer; + total_len -= length; ++ buffer += length; + + for (i = 0; i < num; i++) { +- buffer += length; + cap = (struct usb_dev_cap_header *)buffer; + + if (total_len < sizeof(*cap) || total_len < cap->bLength) { +@@ -983,8 +985,6 @@ int usb_get_bos_descriptor(struct usb_device *dev) + break; + } + +- total_len -= length; +- + if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { + dev_warn(ddev, "descriptor type invalid, skip\n"); + continue; +@@ -1019,7 +1019,11 @@ int usb_get_bos_descriptor(struct usb_device *dev) + default: + break; + } ++ ++ total_len -= length; ++ buffer += length; + } ++ dev->bos->desc->wTotalLength = cpu_to_le16(buffer - buffer0); + + return 0; + +diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h +index 28a2d12a1029..a8279280e88d 100644 +--- a/fs/overlayfs/ovl_entry.h ++++ b/fs/overlayfs/ovl_entry.h +@@ -66,6 +66,7 @@ struct ovl_fs { + bool workdir_locked; + /* Traps in ovl inode cache */ + struct inode *upperdir_trap; ++ struct inode *workbasedir_trap; + struct inode *workdir_trap; + struct inode *indexdir_trap; + /* Inode numbers in all layers do not use the high xino_bits */ +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index b368e2e102fa..afbcb116a7f1 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -212,6 +212,7 @@ static void ovl_free_fs(struct ovl_fs *ofs) + { + unsigned i; + ++ iput(ofs->workbasedir_trap); + iput(ofs->indexdir_trap); + iput(ofs->workdir_trap); + iput(ofs->upperdir_trap); +@@ -1003,6 +1004,25 @@ static int ovl_setup_trap(struct super_block *sb, struct dentry *dir, + return 0; + } + ++/* ++ * Determine how we treat concurrent use of upperdir/workdir based on the ++ * index feature. This is papering over mount leaks of container runtimes, ++ * for example, an old overlay mount is leaked and now its upperdir is ++ * attempted to be used as a lower layer in a new overlay mount. ++ */ ++static int ovl_report_in_use(struct ovl_fs *ofs, const char *name) ++{ ++ if (ofs->config.index) { ++ pr_err("overlayfs: %s is in-use as upperdir/workdir of another mount, mount with '-o index=off' to override exclusive upperdir protection.\n", ++ name); ++ return -EBUSY; ++ } else { ++ pr_warn("overlayfs: %s is in-use as upperdir/workdir of another mount, accessing files from both mounts will result in undefined behavior.\n", ++ name); ++ return 0; ++ } ++} ++ + static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, + struct path *upperpath) + { +@@ -1040,14 +1060,12 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, + upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME); + ofs->upper_mnt = upper_mnt; + +- err = -EBUSY; + if (ovl_inuse_trylock(ofs->upper_mnt->mnt_root)) { + ofs->upperdir_locked = true; +- } else if (ofs->config.index) { +- pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n"); +- goto out; + } else { +- pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); ++ err = ovl_report_in_use(ofs, "upperdir"); ++ if (err) ++ goto out; + } + + err = 0; +@@ -1157,16 +1175,19 @@ static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ofs, + + ofs->workbasedir = dget(workpath.dentry); + +- err = -EBUSY; + if (ovl_inuse_trylock(ofs->workbasedir)) { + ofs->workdir_locked = true; +- } else if (ofs->config.index) { +- pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); +- goto out; + } else { +- pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); ++ err = ovl_report_in_use(ofs, "workdir"); ++ if (err) ++ goto out; + } + ++ err = ovl_setup_trap(sb, ofs->workbasedir, &ofs->workbasedir_trap, ++ "workdir"); ++ if (err) ++ goto out; ++ + err = ovl_make_workdir(sb, ofs, &workpath); + + out: +@@ -1313,16 +1334,16 @@ static int ovl_get_lower_layers(struct super_block *sb, struct ovl_fs *ofs, + if (err < 0) + goto out; + +- err = -EBUSY; +- if (ovl_is_inuse(stack[i].dentry)) { +- pr_err("overlayfs: lowerdir is in-use as upperdir/workdir\n"); +- goto out; +- } +- + err = ovl_setup_trap(sb, stack[i].dentry, &trap, "lowerdir"); + if (err) + goto out; + ++ if (ovl_is_inuse(stack[i].dentry)) { ++ err = ovl_report_in_use(ofs, "lowerdir"); ++ if (err) ++ goto out; ++ } ++ + mnt = clone_private_mount(&stack[i]); + err = PTR_ERR(mnt); + if (IS_ERR(mnt)) { +@@ -1469,8 +1490,8 @@ out_err: + * - another layer of this overlayfs instance + * - upper/work dir of any overlayfs instance + */ +-static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, +- const char *name) ++static int ovl_check_layer(struct super_block *sb, struct ovl_fs *ofs, ++ struct dentry *dentry, const char *name) + { + struct dentry *next = dentry, *parent; + int err = 0; +@@ -1482,13 +1503,11 @@ static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, + + /* Walk back ancestors to root (inclusive) looking for traps */ + while (!err && parent != next) { +- if (ovl_is_inuse(parent)) { +- err = -EBUSY; +- pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n", +- name); +- } else if (ovl_lookup_trap_inode(sb, parent)) { ++ if (ovl_lookup_trap_inode(sb, parent)) { + err = -ELOOP; + pr_err("overlayfs: overlapping %s path\n", name); ++ } else if (ovl_is_inuse(parent)) { ++ err = ovl_report_in_use(ofs, name); + } + next = parent; + parent = dget_parent(next); +@@ -1509,7 +1528,8 @@ static int ovl_check_overlapping_layers(struct super_block *sb, + int i, err; + + if (ofs->upper_mnt) { +- err = ovl_check_layer(sb, ofs->upper_mnt->mnt_root, "upperdir"); ++ err = ovl_check_layer(sb, ofs, ofs->upper_mnt->mnt_root, ++ "upperdir"); + if (err) + return err; + +@@ -1520,13 +1540,14 @@ static int ovl_check_overlapping_layers(struct super_block *sb, + * workbasedir. In that case, we already have their traps in + * inode cache and we will catch that case on lookup. + */ +- err = ovl_check_layer(sb, ofs->workbasedir, "workdir"); ++ err = ovl_check_layer(sb, ofs, ofs->workbasedir, "workdir"); + if (err) + return err; + } + + for (i = 0; i < ofs->numlower; i++) { +- err = ovl_check_layer(sb, ofs->lower_layers[i].mnt->mnt_root, ++ err = ovl_check_layer(sb, ofs, ++ ofs->lower_layers[i].mnt->mnt_root, + "lowerdir"); + if (err) + return err; +diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h +index a16fbe9a2a67..aa99c73c3fbd 100644 +--- a/include/net/pkt_sched.h ++++ b/include/net/pkt_sched.h +@@ -118,7 +118,12 @@ void __qdisc_run(struct Qdisc *q); + static inline void qdisc_run(struct Qdisc *q) + { + if (qdisc_run_begin(q)) { +- __qdisc_run(q); ++ /* NOLOCK qdisc must check 'state' under the qdisc seqlock ++ * to avoid racing with dev_qdisc_reset() ++ */ ++ if (!(q->flags & TCQ_F_NOLOCK) || ++ likely(!test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) ++ __qdisc_run(q); + qdisc_run_end(q); + } + } +diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h +index d9112de85261..43f4a818d88f 100644 +--- a/include/net/sock_reuseport.h ++++ b/include/net/sock_reuseport.h +@@ -21,7 +21,8 @@ struct sock_reuseport { + unsigned int synq_overflow_ts; + /* ID stays the same even after the size of socks[] grows. */ + unsigned int reuseport_id; +- bool bind_inany; ++ unsigned int bind_inany:1; ++ unsigned int has_conns:1; + struct bpf_prog __rcu *prog; /* optional BPF sock selector */ + struct sock *socks[0]; /* array of sock pointers */ + }; +@@ -37,6 +38,23 @@ extern struct sock *reuseport_select_sock(struct sock *sk, + extern int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog); + extern int reuseport_detach_prog(struct sock *sk); + ++static inline bool reuseport_has_conns(struct sock *sk, bool set) ++{ ++ struct sock_reuseport *reuse; ++ bool ret = false; ++ ++ rcu_read_lock(); ++ reuse = rcu_dereference(sk->sk_reuseport_cb); ++ if (reuse) { ++ if (set) ++ reuse->has_conns = 1; ++ ret = reuse->has_conns; ++ } ++ rcu_read_unlock(); ++ ++ return ret; ++} ++ + int reuseport_get_id(struct sock_reuseport *reuse); + + #endif /* _SOCK_REUSEPORT_H */ +diff --git a/net/core/dev.c b/net/core/dev.c +index 5156c0edebe8..4ed9df74eb8a 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3467,18 +3467,22 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, + qdisc_calculate_pkt_len(skb, q); + + if (q->flags & TCQ_F_NOLOCK) { +- if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) { +- __qdisc_drop(skb, &to_free); +- rc = NET_XMIT_DROP; +- } else if ((q->flags & TCQ_F_CAN_BYPASS) && q->empty && +- qdisc_run_begin(q)) { ++ if ((q->flags & TCQ_F_CAN_BYPASS) && q->empty && ++ qdisc_run_begin(q)) { ++ if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, ++ &q->state))) { ++ __qdisc_drop(skb, &to_free); ++ rc = NET_XMIT_DROP; ++ goto end_run; ++ } + qdisc_bstats_cpu_update(q, skb); + ++ rc = NET_XMIT_SUCCESS; + if (sch_direct_xmit(skb, q, dev, txq, NULL, true)) + __qdisc_run(q); + ++end_run: + qdisc_run_end(q); +- rc = NET_XMIT_SUCCESS; + } else { + rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK; + qdisc_run(q); +diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c +index 9408f9264d05..f3ceec93f392 100644 +--- a/net/core/sock_reuseport.c ++++ b/net/core/sock_reuseport.c +@@ -295,8 +295,19 @@ struct sock *reuseport_select_sock(struct sock *sk, + + select_by_hash: + /* no bpf or invalid bpf result: fall back to hash usage */ +- if (!sk2) +- sk2 = reuse->socks[reciprocal_scale(hash, socks)]; ++ if (!sk2) { ++ int i, j; ++ ++ i = j = reciprocal_scale(hash, socks); ++ while (reuse->socks[i]->sk_state == TCP_ESTABLISHED) { ++ i++; ++ if (i >= reuse->num_socks) ++ i = 0; ++ if (i == j) ++ goto out; ++ } ++ sk2 = reuse->socks[i]; ++ } + } + + out: +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index 3abd173ebacb..96f787cf9b6e 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -623,6 +623,8 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master) + tag_protocol = ds->ops->get_tag_protocol(ds, dp->index); + tag_ops = dsa_tag_driver_get(tag_protocol); + if (IS_ERR(tag_ops)) { ++ if (PTR_ERR(tag_ops) == -ENOPROTOOPT) ++ return -EPROBE_DEFER; + dev_warn(ds->dev, "No tagger for this switch\n"); + return PTR_ERR(tag_ops); + } +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index 7bd29e694603..9a0fe0c2fa02 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -15,6 +15,7 @@ + #include <net/sock.h> + #include <net/route.h> + #include <net/tcp_states.h> ++#include <net/sock_reuseport.h> + + int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + { +@@ -69,6 +70,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len + } + inet->inet_daddr = fl4->daddr; + inet->inet_dport = usin->sin_port; ++ reuseport_has_conns(sk, true); + sk->sk_state = TCP_ESTABLISHED; + sk_set_txhash(sk); + inet->inet_id = jiffies; +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index d88821c794fb..16486c8b708b 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -423,12 +423,13 @@ static struct sock *udp4_lib_lookup2(struct net *net, + score = compute_score(sk, net, saddr, sport, + daddr, hnum, dif, sdif); + if (score > badness) { +- if (sk->sk_reuseport) { ++ if (sk->sk_reuseport && ++ sk->sk_state != TCP_ESTABLISHED) { + hash = udp_ehashfn(net, daddr, hnum, + saddr, sport); + result = reuseport_select_sock(sk, hash, skb, + sizeof(struct udphdr)); +- if (result) ++ if (result && !reuseport_has_conns(sk, false)) + return result; + } + badness = score; +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index 9ab897ded4df..96f939248d2f 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -27,6 +27,7 @@ + #include <net/ip6_route.h> + #include <net/tcp_states.h> + #include <net/dsfield.h> ++#include <net/sock_reuseport.h> + + #include <linux/errqueue.h> + #include <linux/uaccess.h> +@@ -254,6 +255,7 @@ ipv4_connected: + goto out; + } + ++ reuseport_has_conns(sk, true); + sk->sk_state = TCP_ESTABLISHED; + sk_set_txhash(sk); + out: +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index dd2d0b963260..d5779d6a6065 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -968,7 +968,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, + if (unlikely(!tun_info || + !(tun_info->mode & IP_TUNNEL_INFO_TX) || + ip_tunnel_info_af(tun_info) != AF_INET6)) +- return -EINVAL; ++ goto tx_err; + + key = &tun_info->key; + memset(&fl6, 0, sizeof(fl6)); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 827fe7385078..5995fdc99d3f 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -158,13 +158,14 @@ static struct sock *udp6_lib_lookup2(struct net *net, + score = compute_score(sk, net, saddr, sport, + daddr, hnum, dif, sdif); + if (score > badness) { +- if (sk->sk_reuseport) { ++ if (sk->sk_reuseport && ++ sk->sk_state != TCP_ESTABLISHED) { + hash = udp6_ehashfn(net, daddr, hnum, + saddr, sport); + + result = reuseport_select_sock(sk, hash, skb, + sizeof(struct udphdr)); +- if (result) ++ if (result && !reuseport_has_conns(sk, false)) + return result; + } + result = sk; +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index ac28f6a5d70e..17bd8f539bc7 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -985,6 +985,9 @@ static void qdisc_destroy(struct Qdisc *qdisc) + + void qdisc_put(struct Qdisc *qdisc) + { ++ if (!qdisc) ++ return; ++ + if (qdisc->flags & TCQ_F_BUILTIN || + !refcount_dec_and_test(&qdisc->refcnt)) + return; +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index fd05ae1437a9..c9cfc796eccf 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -10659,9 +10659,11 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, + hyst = wdev->cqm_config->rssi_hyst; + n = wdev->cqm_config->n_rssi_thresholds; + +- for (i = 0; i < n; i++) ++ for (i = 0; i < n; i++) { ++ i = array_index_nospec(i, n); + if (last < wdev->cqm_config->rssi_thresholds[i]) + break; ++ } + + low_index = i - 1; + if (low_index >= 0) { +diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c +index 5294abb3f178..8ffd07e2a160 100644 +--- a/virt/kvm/coalesced_mmio.c ++++ b/virt/kvm/coalesced_mmio.c +@@ -40,7 +40,7 @@ static int coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev, + return 1; + } + +-static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev) ++static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev, u32 last) + { + struct kvm_coalesced_mmio_ring *ring; + unsigned avail; +@@ -52,7 +52,7 @@ static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev) + * there is always one unused entry in the buffer + */ + ring = dev->kvm->coalesced_mmio_ring; +- avail = (ring->first - ring->last - 1) % KVM_COALESCED_MMIO_MAX; ++ avail = (ring->first - last - 1) % KVM_COALESCED_MMIO_MAX; + if (avail == 0) { + /* full */ + return 0; +@@ -67,25 +67,28 @@ static int coalesced_mmio_write(struct kvm_vcpu *vcpu, + { + struct kvm_coalesced_mmio_dev *dev = to_mmio(this); + struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring; ++ __u32 insert; + + if (!coalesced_mmio_in_range(dev, addr, len)) + return -EOPNOTSUPP; + + spin_lock(&dev->kvm->ring_lock); + +- if (!coalesced_mmio_has_room(dev)) { ++ insert = READ_ONCE(ring->last); ++ if (!coalesced_mmio_has_room(dev, insert) || ++ insert >= KVM_COALESCED_MMIO_MAX) { + spin_unlock(&dev->kvm->ring_lock); + return -EOPNOTSUPP; + } + + /* copy data in first free entry of the ring */ + +- ring->coalesced_mmio[ring->last].phys_addr = addr; +- ring->coalesced_mmio[ring->last].len = len; +- memcpy(ring->coalesced_mmio[ring->last].data, val, len); +- ring->coalesced_mmio[ring->last].pio = dev->zone.pio; ++ ring->coalesced_mmio[insert].phys_addr = addr; ++ ring->coalesced_mmio[insert].len = len; ++ memcpy(ring->coalesced_mmio[insert].data, val, len); ++ ring->coalesced_mmio[insert].pio = dev->zone.pio; + smp_wmb(); +- ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX; ++ ring->last = (insert + 1) % KVM_COALESCED_MMIO_MAX; + spin_unlock(&dev->kvm->ring_lock); + return 0; + } |