diff options
author | Mike Pagano <mpagano@gentoo.org> | 2021-11-21 15:42:40 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2021-11-21 15:42:40 -0500 |
commit | ffcf9f68f9a2e99641b96e1629e477e770e99f48 (patch) | |
tree | 1d0733baa5daa8b3366bf787c472d2856ef268b0 /1080_linux-5.10.81.patch | |
parent | Linux patch 5.10.80 (diff) | |
download | linux-patches-ffcf9f68f9a2e99641b96e1629e477e770e99f48.tar.gz linux-patches-ffcf9f68f9a2e99641b96e1629e477e770e99f48.tar.bz2 linux-patches-ffcf9f68f9a2e99641b96e1629e477e770e99f48.zip |
Linux patch 5.10.815.10-88
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
Diffstat (limited to '1080_linux-5.10.81.patch')
-rw-r--r-- | 1080_linux-5.10.81.patch | 1173 |
1 files changed, 1173 insertions, 0 deletions
diff --git a/1080_linux-5.10.81.patch b/1080_linux-5.10.81.patch new file mode 100644 index 00000000..0a03b38e --- /dev/null +++ b/1080_linux-5.10.81.patch @@ -0,0 +1,1173 @@ +diff --git a/Makefile b/Makefile +index 71fdc74801e0a..1baeadb574f1c 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 10 +-SUBLEVEL = 80 ++SUBLEVEL = 81 + EXTRAVERSION = + NAME = Dare mighty things + +diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S +index 9c76d50a5654b..3da39140babcf 100644 +--- a/arch/parisc/kernel/entry.S ++++ b/arch/parisc/kernel/entry.S +@@ -1849,7 +1849,7 @@ syscall_restore: + + /* Are we being ptraced? */ + LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 +- ldi _TIF_SYSCALL_TRACE_MASK,%r2 ++ ldi _TIF_SINGLESTEP|_TIF_BLOCKSTEP,%r2 + and,COND(=) %r19,%r2,%r0 + b,n syscall_restore_rfi + +diff --git a/arch/x86/include/asm/insn-eval.h b/arch/x86/include/asm/insn-eval.h +index 98b4dae5e8bc8..c1438f9239e46 100644 +--- a/arch/x86/include/asm/insn-eval.h ++++ b/arch/x86/include/asm/insn-eval.h +@@ -21,6 +21,7 @@ int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs); + int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs); + unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx); + int insn_get_code_seg_params(struct pt_regs *regs); ++unsigned long insn_get_effective_ip(struct pt_regs *regs); + int insn_fetch_from_user(struct pt_regs *regs, + unsigned char buf[MAX_INSN_SIZE]); + int insn_fetch_from_user_inatomic(struct pt_regs *regs, +diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h +index 50d02db723177..d428d611a43a9 100644 +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -534,6 +534,7 @@ struct thread_struct { + */ + unsigned long iopl_emul; + ++ unsigned int iopl_warn:1; + unsigned int sig_on_uaccess_err:1; + + /* Floating point and extended processor state */ +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 145a7ac0c19aa..0aa1baf9a3afc 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -138,6 +138,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, + frame->ret_addr = (unsigned long) ret_from_fork; + p->thread.sp = (unsigned long) fork_frame; + p->thread.io_bitmap = NULL; ++ p->thread.iopl_warn = 0; + memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); + + #ifdef CONFIG_X86_64 +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 143fcb8af38f4..2d4ecd50e69b8 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -523,6 +523,37 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs, + + #define GPFSTR "general protection fault" + ++static bool fixup_iopl_exception(struct pt_regs *regs) ++{ ++ struct thread_struct *t = ¤t->thread; ++ unsigned char byte; ++ unsigned long ip; ++ ++ if (!IS_ENABLED(CONFIG_X86_IOPL_IOPERM) || t->iopl_emul != 3) ++ return false; ++ ++ ip = insn_get_effective_ip(regs); ++ if (!ip) ++ return false; ++ ++ if (get_user(byte, (const char __user *)ip)) ++ return false; ++ ++ if (byte != 0xfa && byte != 0xfb) ++ return false; ++ ++ if (!t->iopl_warn && printk_ratelimit()) { ++ pr_err("%s[%d] attempts to use CLI/STI, pretending it's a NOP, ip:%lx", ++ current->comm, task_pid_nr(current), ip); ++ print_vma_addr(KERN_CONT " in ", ip); ++ pr_cont("\n"); ++ t->iopl_warn = 1; ++ } ++ ++ regs->ip += 1; ++ return true; ++} ++ + DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) + { + char desc[sizeof(GPFSTR) + 50 + 2*sizeof(unsigned long) + 1] = GPFSTR; +@@ -548,6 +579,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) + tsk = current; + + if (user_mode(regs)) { ++ if (fixup_iopl_exception(regs)) ++ goto exit; ++ + tsk->thread.error_code = error_code; + tsk->thread.trap_nr = X86_TRAP_GP; + +diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c +index bb0b3fe1e0a02..c6a19c88af547 100644 +--- a/arch/x86/lib/insn-eval.c ++++ b/arch/x86/lib/insn-eval.c +@@ -1415,7 +1415,7 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) + } + } + +-static unsigned long insn_get_effective_ip(struct pt_regs *regs) ++unsigned long insn_get_effective_ip(struct pt_regs *regs) + { + unsigned long seg_base = 0; + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index f0fa0c8e7ec60..ee537a9f1d1a4 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -228,19 +228,6 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) + blk_mq_unfreeze_queue(lo->lo_queue); + } + +-/** +- * loop_validate_block_size() - validates the passed in block size +- * @bsize: size to validate +- */ +-static int +-loop_validate_block_size(unsigned short bsize) +-{ +- if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) +- return -EINVAL; +- +- return 0; +-} +- + /** + * loop_set_size() - sets device size and notifies userspace + * @lo: struct loop_device to set the size for +@@ -1121,7 +1108,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + } + + if (config->block_size) { +- error = loop_validate_block_size(config->block_size); ++ error = blk_validate_block_size(config->block_size); + if (error) + goto out_unlock; + } +@@ -1617,7 +1604,7 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) + if (lo->lo_state != Lo_bound) + return -ENXIO; + +- err = loop_validate_block_size(arg); ++ err = blk_validate_block_size(arg); + if (err) + return err; + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +index 6ef30252bfe0a..143b2cb13bf94 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +@@ -21,7 +21,6 @@ + #include <linux/delay.h> + #include <linux/mfd/syscon.h> + #include <linux/regmap.h> +-#include <linux/pm_runtime.h> + + #include "stmmac_platform.h" + +@@ -1336,9 +1335,6 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv) + return ret; + } + +- pm_runtime_enable(dev); +- pm_runtime_get_sync(dev); +- + if (bsp_priv->integrated_phy) + rk_gmac_integrated_phy_powerup(bsp_priv); + +@@ -1347,14 +1343,9 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv) + + static void rk_gmac_powerdown(struct rk_priv_data *gmac) + { +- struct device *dev = &gmac->pdev->dev; +- + if (gmac->integrated_phy) + rk_gmac_integrated_phy_powerdown(gmac); + +- pm_runtime_put_sync(dev); +- pm_runtime_disable(dev); +- + phy_power_on(gmac, false); + gmac_clk_enable(gmac, false); + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index 727e68dfaf1c2..a4ca283e02284 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -270,6 +270,7 @@ void stmmac_disable_eee_mode(struct stmmac_priv *priv); + bool stmmac_eee_init(struct stmmac_priv *priv); + int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt); + int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size); ++int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled); + + #if IS_ENABLED(CONFIG_STMMAC_SELFTESTS) + void stmmac_selftest_run(struct net_device *dev, +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 0ac61e7ab43cd..4a75e73f06bbd 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -28,6 +28,7 @@ + #include <linux/if_vlan.h> + #include <linux/dma-mapping.h> + #include <linux/slab.h> ++#include <linux/pm_runtime.h> + #include <linux/prefetch.h> + #include <linux/pinctrl/consumer.h> + #ifdef CONFIG_DEBUG_FS +@@ -113,6 +114,28 @@ static void stmmac_exit_fs(struct net_device *dev); + + #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) + ++int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled) ++{ ++ int ret = 0; ++ ++ if (enabled) { ++ ret = clk_prepare_enable(priv->plat->stmmac_clk); ++ if (ret) ++ return ret; ++ ret = clk_prepare_enable(priv->plat->pclk); ++ if (ret) { ++ clk_disable_unprepare(priv->plat->stmmac_clk); ++ return ret; ++ } ++ } else { ++ clk_disable_unprepare(priv->plat->stmmac_clk); ++ clk_disable_unprepare(priv->plat->pclk); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(stmmac_bus_clks_config); ++ + /** + * stmmac_verify_args - verify the driver parameters. + * Description: it checks the driver parameters and set a default in case of +@@ -2792,6 +2815,12 @@ static int stmmac_open(struct net_device *dev) + u32 chan; + int ret; + ++ ret = pm_runtime_get_sync(priv->device); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->device); ++ return ret; ++ } ++ + if (priv->hw->pcs != STMMAC_PCS_TBI && + priv->hw->pcs != STMMAC_PCS_RTBI && + priv->hw->xpcs == NULL) { +@@ -2800,7 +2829,7 @@ static int stmmac_open(struct net_device *dev) + netdev_err(priv->dev, + "%s: Cannot attach to PHY (error: %d)\n", + __func__, ret); +- return ret; ++ goto init_phy_error; + } + } + +@@ -2915,6 +2944,8 @@ init_error: + free_dma_desc_resources(priv); + dma_desc_error: + phylink_disconnect_phy(priv->phylink); ++init_phy_error: ++ pm_runtime_put(priv->device); + return ret; + } + +@@ -2965,6 +2996,8 @@ static int stmmac_release(struct net_device *dev) + + stmmac_release_ptp(priv); + ++ pm_runtime_put(priv->device); ++ + return 0; + } + +@@ -4291,12 +4324,21 @@ static int stmmac_set_mac_address(struct net_device *ndev, void *addr) + struct stmmac_priv *priv = netdev_priv(ndev); + int ret = 0; + ++ ret = pm_runtime_get_sync(priv->device); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->device); ++ return ret; ++ } ++ + ret = eth_mac_addr(ndev, addr); + if (ret) +- return ret; ++ goto set_mac_error; + + stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0); + ++set_mac_error: ++ pm_runtime_put(priv->device); ++ + return ret; + } + +@@ -4616,6 +4658,12 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi + bool is_double = false; + int ret; + ++ ret = pm_runtime_get_sync(priv->device); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->device); ++ return ret; ++ } ++ + if (be16_to_cpu(proto) == ETH_P_8021AD) + is_double = true; + +@@ -4624,10 +4672,15 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi + if (priv->hw->num_vlan) { + ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); + if (ret) +- return ret; ++ goto del_vlan_error; + } + +- return stmmac_vlan_update(priv, is_double); ++ ret = stmmac_vlan_update(priv, is_double); ++ ++del_vlan_error: ++ pm_runtime_put(priv->device); ++ ++ return ret; + } + + static const struct net_device_ops stmmac_netdev_ops = { +@@ -5066,6 +5119,10 @@ int stmmac_dvr_probe(struct device *device, + + stmmac_check_pcs_mode(priv); + ++ pm_runtime_get_noresume(device); ++ pm_runtime_set_active(device); ++ pm_runtime_enable(device); ++ + if (priv->hw->pcs != STMMAC_PCS_TBI && + priv->hw->pcs != STMMAC_PCS_RTBI) { + /* MDIO bus Registration */ +@@ -5103,6 +5160,11 @@ int stmmac_dvr_probe(struct device *device, + stmmac_init_fs(ndev); + #endif + ++ /* Let pm_runtime_put() disable the clocks. ++ * If CONFIG_PM is not enabled, the clocks will stay powered. ++ */ ++ pm_runtime_put(device); ++ + return ret; + + error_serdes_powerup: +@@ -5152,8 +5214,8 @@ int stmmac_dvr_remove(struct device *dev) + phylink_destroy(priv->phylink); + if (priv->plat->stmmac_rst) + reset_control_assert(priv->plat->stmmac_rst); +- clk_disable_unprepare(priv->plat->pclk); +- clk_disable_unprepare(priv->plat->stmmac_clk); ++ pm_runtime_put(dev); ++ pm_runtime_disable(dev); + if (priv->hw->pcs != STMMAC_PCS_TBI && + priv->hw->pcs != STMMAC_PCS_RTBI) + stmmac_mdio_unregister(ndev); +@@ -5176,6 +5238,7 @@ int stmmac_suspend(struct device *dev) + struct net_device *ndev = dev_get_drvdata(dev); + struct stmmac_priv *priv = netdev_priv(ndev); + u32 chan; ++ int ret; + + if (!ndev || !netif_running(ndev)) + return 0; +@@ -5219,8 +5282,11 @@ int stmmac_suspend(struct device *dev) + pinctrl_pm_select_sleep_state(priv->device); + /* Disable clock in case of PWM is off */ + clk_disable_unprepare(priv->plat->clk_ptp_ref); +- clk_disable_unprepare(priv->plat->pclk); +- clk_disable_unprepare(priv->plat->stmmac_clk); ++ ret = pm_runtime_force_suspend(dev); ++ if (ret) { ++ mutex_unlock(&priv->lock); ++ return ret; ++ } + } + mutex_unlock(&priv->lock); + +@@ -5286,8 +5352,9 @@ int stmmac_resume(struct device *dev) + } else { + pinctrl_pm_select_default_state(priv->device); + /* enable the clk previously disabled */ +- clk_prepare_enable(priv->plat->stmmac_clk); +- clk_prepare_enable(priv->plat->pclk); ++ ret = pm_runtime_force_resume(dev); ++ if (ret) ++ return ret; + if (priv->plat->clk_ptp_ref) + clk_prepare_enable(priv->plat->clk_ptp_ref); + /* reset the phy so that it's ready */ +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +index 678726c62a8af..7c1a14b256da3 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +@@ -15,6 +15,7 @@ + #include <linux/iopoll.h> + #include <linux/mii.h> + #include <linux/of_mdio.h> ++#include <linux/pm_runtime.h> + #include <linux/phy.h> + #include <linux/property.h> + #include <linux/slab.h> +@@ -87,21 +88,29 @@ static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) + u32 tmp, addr, value = MII_XGMAC_BUSY; + int ret; + ++ ret = pm_runtime_get_sync(priv->device); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->device); ++ return ret; ++ } ++ + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, +- !(tmp & MII_XGMAC_BUSY), 100, 10000)) +- return -EBUSY; ++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) { ++ ret = -EBUSY; ++ goto err_disable_clks; ++ } + + if (phyreg & MII_ADDR_C45) { + phyreg &= ~MII_ADDR_C45; + + ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr); + if (ret) +- return ret; ++ goto err_disable_clks; + } else { + ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr); + if (ret) +- return ret; ++ goto err_disable_clks; + + value |= MII_XGMAC_SADDR; + } +@@ -112,8 +121,10 @@ static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) + + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, +- !(tmp & MII_XGMAC_BUSY), 100, 10000)) +- return -EBUSY; ++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) { ++ ret = -EBUSY; ++ goto err_disable_clks; ++ } + + /* Set the MII address register to read */ + writel(addr, priv->ioaddr + mii_address); +@@ -121,11 +132,18 @@ static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) + + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, +- !(tmp & MII_XGMAC_BUSY), 100, 10000)) +- return -EBUSY; ++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) { ++ ret = -EBUSY; ++ goto err_disable_clks; ++ } + + /* Read the data from the MII data register */ +- return readl(priv->ioaddr + mii_data) & GENMASK(15, 0); ++ ret = (int)readl(priv->ioaddr + mii_data) & GENMASK(15, 0); ++ ++err_disable_clks: ++ pm_runtime_put(priv->device); ++ ++ return ret; + } + + static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr, +@@ -138,21 +156,29 @@ static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr, + u32 addr, tmp, value = MII_XGMAC_BUSY; + int ret; + ++ ret = pm_runtime_get_sync(priv->device); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->device); ++ return ret; ++ } ++ + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, +- !(tmp & MII_XGMAC_BUSY), 100, 10000)) +- return -EBUSY; ++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) { ++ ret = -EBUSY; ++ goto err_disable_clks; ++ } + + if (phyreg & MII_ADDR_C45) { + phyreg &= ~MII_ADDR_C45; + + ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr); + if (ret) +- return ret; ++ goto err_disable_clks; + } else { + ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr); + if (ret) +- return ret; ++ goto err_disable_clks; + + value |= MII_XGMAC_SADDR; + } +@@ -164,16 +190,23 @@ static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr, + + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, +- !(tmp & MII_XGMAC_BUSY), 100, 10000)) +- return -EBUSY; ++ !(tmp & MII_XGMAC_BUSY), 100, 10000)) { ++ ret = -EBUSY; ++ goto err_disable_clks; ++ } + + /* Set the MII address register to write */ + writel(addr, priv->ioaddr + mii_address); + writel(value, priv->ioaddr + mii_data); + + /* Wait until any existing MII operation is complete */ +- return readl_poll_timeout(priv->ioaddr + mii_data, tmp, +- !(tmp & MII_XGMAC_BUSY), 100, 10000); ++ ret = readl_poll_timeout(priv->ioaddr + mii_data, tmp, ++ !(tmp & MII_XGMAC_BUSY), 100, 10000); ++ ++err_disable_clks: ++ pm_runtime_put(priv->device); ++ ++ return ret; + } + + /** +@@ -196,6 +229,12 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) + int data = 0; + u32 v; + ++ data = pm_runtime_get_sync(priv->device); ++ if (data < 0) { ++ pm_runtime_put_noidle(priv->device); ++ return data; ++ } ++ + value |= (phyaddr << priv->hw->mii.addr_shift) + & priv->hw->mii.addr_mask; + value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; +@@ -216,19 +255,26 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) + } + + if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), +- 100, 10000)) +- return -EBUSY; ++ 100, 10000)) { ++ data = -EBUSY; ++ goto err_disable_clks; ++ } + + writel(data, priv->ioaddr + mii_data); + writel(value, priv->ioaddr + mii_address); + + if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), +- 100, 10000)) +- return -EBUSY; ++ 100, 10000)) { ++ data = -EBUSY; ++ goto err_disable_clks; ++ } + + /* Read the data from the MII data register */ + data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK; + ++err_disable_clks: ++ pm_runtime_put(priv->device); ++ + return data; + } + +@@ -247,10 +293,16 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, + struct stmmac_priv *priv = netdev_priv(ndev); + unsigned int mii_address = priv->hw->mii.addr; + unsigned int mii_data = priv->hw->mii.data; ++ int ret, data = phydata; + u32 value = MII_BUSY; +- int data = phydata; + u32 v; + ++ ret = pm_runtime_get_sync(priv->device); ++ if (ret < 0) { ++ pm_runtime_put_noidle(priv->device); ++ return ret; ++ } ++ + value |= (phyaddr << priv->hw->mii.addr_shift) + & priv->hw->mii.addr_mask; + value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; +@@ -275,16 +327,23 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, + + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), +- 100, 10000)) +- return -EBUSY; ++ 100, 10000)) { ++ ret = -EBUSY; ++ goto err_disable_clks; ++ } + + /* Set the MII address register to write */ + writel(data, priv->ioaddr + mii_data); + writel(value, priv->ioaddr + mii_address); + + /* Wait until any existing MII operation is complete */ +- return readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), +- 100, 10000); ++ ret = readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), ++ 100, 10000); ++ ++err_disable_clks: ++ pm_runtime_put(priv->device); ++ ++ return ret; + } + + /** +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 48186cd32ce10..035f9aef4308f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -720,7 +720,6 @@ int stmmac_pltfr_remove(struct platform_device *pdev) + } + EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); + +-#ifdef CONFIG_PM_SLEEP + /** + * stmmac_pltfr_suspend + * @dev: device pointer +@@ -728,7 +727,7 @@ EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); + * call the main suspend function and then, if required, on some platform, it + * can call an exit helper. + */ +-static int stmmac_pltfr_suspend(struct device *dev) ++static int __maybe_unused stmmac_pltfr_suspend(struct device *dev) + { + int ret; + struct net_device *ndev = dev_get_drvdata(dev); +@@ -749,7 +748,7 @@ static int stmmac_pltfr_suspend(struct device *dev) + * the main resume function, on some platforms, it can call own init helper + * if required. + */ +-static int stmmac_pltfr_resume(struct device *dev) ++static int __maybe_unused stmmac_pltfr_resume(struct device *dev) + { + struct net_device *ndev = dev_get_drvdata(dev); + struct stmmac_priv *priv = netdev_priv(ndev); +@@ -760,10 +759,29 @@ static int stmmac_pltfr_resume(struct device *dev) + + return stmmac_resume(dev); + } +-#endif /* CONFIG_PM_SLEEP */ + +-SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend, +- stmmac_pltfr_resume); ++static int __maybe_unused stmmac_runtime_suspend(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ ++ stmmac_bus_clks_config(priv, false); ++ ++ return 0; ++} ++ ++static int __maybe_unused stmmac_runtime_resume(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ ++ return stmmac_bus_clks_config(priv, true); ++} ++ ++const struct dev_pm_ops stmmac_pltfr_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume) ++ SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL) ++}; + EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops); + + MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support"); +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index a7a1c74113483..db7475dc601f5 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -396,18 +396,6 @@ static void free_msi_irqs(struct pci_dev *dev) + for (i = 0; i < entry->nvec_used; i++) + BUG_ON(irq_has_action(entry->irq + i)); + +- pci_msi_teardown_msi_irqs(dev); +- +- list_for_each_entry_safe(entry, tmp, msi_list, list) { +- if (entry->msi_attrib.is_msix) { +- if (list_is_last(&entry->list, msi_list)) +- iounmap(entry->mask_base); +- } +- +- list_del(&entry->list); +- free_msi_entry(entry); +- } +- + if (dev->msi_irq_groups) { + sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups); + msi_attrs = dev->msi_irq_groups[0]->attrs; +@@ -423,6 +411,18 @@ static void free_msi_irqs(struct pci_dev *dev) + kfree(dev->msi_irq_groups); + dev->msi_irq_groups = NULL; + } ++ ++ pci_msi_teardown_msi_irqs(dev); ++ ++ list_for_each_entry_safe(entry, tmp, msi_list, list) { ++ if (entry->msi_attrib.is_msix) { ++ if (list_is_last(&entry->list, msi_list)) ++ iounmap(entry->mask_base); ++ } ++ ++ list_del(&entry->list); ++ free_msi_entry(entry); ++ } + } + + static void pci_intx_for_msi(struct pci_dev *dev, int enable) +@@ -592,6 +592,9 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) + goto out; + + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); ++ /* Lies, damned lies, and MSIs */ ++ if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING) ++ control |= PCI_MSI_FLAGS_MASKBIT; + + entry->msi_attrib.is_msix = 0; + entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT); +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index fb91b2d7b1c59..bb863ddb59bfc 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -5756,3 +5756,9 @@ static void apex_pci_fixup_class(struct pci_dev *pdev) + } + DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a, + PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class); ++ ++static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) ++{ ++ pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING; ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup); +diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c +index 6379f26a335f6..9233f7e744544 100644 +--- a/drivers/thermal/thermal_of.c ++++ b/drivers/thermal/thermal_of.c +@@ -89,7 +89,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_temp) ++ if (!data->ops || !data->ops->get_temp) + return -EINVAL; + + return data->ops->get_temp(data->sensor_data, temp); +@@ -186,6 +186,9 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + ++ if (!data->ops || !data->ops->set_emul_temp) ++ return -EINVAL; ++ + return data->ops->set_emul_temp(data->sensor_data, temp); + } + +@@ -194,7 +197,7 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_trend) ++ if (!data->ops || !data->ops->get_trend) + return -EINVAL; + + return data->ops->get_trend(data->sensor_data, trip, trend); +@@ -301,7 +304,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, + if (trip >= data->ntrips || trip < 0) + return -EDOM; + +- if (data->ops->set_trip_temp) { ++ if (data->ops && data->ops->set_trip_temp) { + int ret; + + ret = data->ops->set_trip_temp(data->sensor_data, trip, temp); +diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c +index 86fd3bf62af61..8cb2cf612e49b 100644 +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -278,11 +278,10 @@ static inline bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, + + /* callers must be with collection lock held */ + static int z_erofs_attach_page(struct z_erofs_collector *clt, +- struct page *page, +- enum z_erofs_page_type type) ++ struct page *page, enum z_erofs_page_type type, ++ bool pvec_safereuse) + { + int ret; +- bool occupied; + + /* give priority for inplaceio */ + if (clt->mode >= COLLECT_PRIMARY && +@@ -290,10 +289,9 @@ static int z_erofs_attach_page(struct z_erofs_collector *clt, + z_erofs_try_inplace_io(clt, page)) + return 0; + +- ret = z_erofs_pagevec_enqueue(&clt->vector, +- page, type, &occupied); ++ ret = z_erofs_pagevec_enqueue(&clt->vector, page, type, ++ pvec_safereuse); + clt->cl->vcnt += (unsigned int)ret; +- + return ret ? 0 : -EAGAIN; + } + +@@ -647,7 +645,8 @@ hitted: + tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); + + retry: +- err = z_erofs_attach_page(clt, page, page_type); ++ err = z_erofs_attach_page(clt, page, page_type, ++ clt->mode >= COLLECT_PRIMARY_FOLLOWED); + /* should allocate an additional staging page for pagevec */ + if (err == -EAGAIN) { + struct page *const newpage = +@@ -655,7 +654,7 @@ retry: + + newpage->mapping = Z_EROFS_MAPPING_STAGING; + err = z_erofs_attach_page(clt, newpage, +- Z_EROFS_PAGE_TYPE_EXCLUSIVE); ++ Z_EROFS_PAGE_TYPE_EXCLUSIVE, true); + if (!err) + goto retry; + } +diff --git a/fs/erofs/zpvec.h b/fs/erofs/zpvec.h +index 1d67cbd387042..52898176ef31d 100644 +--- a/fs/erofs/zpvec.h ++++ b/fs/erofs/zpvec.h +@@ -108,12 +108,17 @@ static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, + static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, + struct page *page, + enum z_erofs_page_type type, +- bool *occupied) ++ bool pvec_safereuse) + { +- *occupied = false; +- if (!ctor->next && type) +- if (ctor->index + 1 == ctor->nr) ++ if (!ctor->next) { ++ /* some pages cannot be reused as pvec safely without I/O */ ++ if (type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && !pvec_safereuse) ++ type = Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED; ++ ++ if (type != Z_EROFS_PAGE_TYPE_EXCLUSIVE && ++ ctor->index + 1 == ctor->nr) + return false; ++ } + + if (ctor->index >= ctor->nr) + z_erofs_pagevec_ctor_pagedown(ctor, false); +@@ -125,7 +130,6 @@ static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, + /* should remind that collector->next never equal to 1, 2 */ + if (type == (uintptr_t)ctor->next) { + ctor->next = page; +- *occupied = true; + } + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type); + return true; +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 4ba17736b614f..98fdf5a31fd66 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -59,6 +59,14 @@ struct blk_keyslot_manager; + */ + #define BLKCG_MAX_POLS 5 + ++static inline int blk_validate_block_size(unsigned int bsize) ++{ ++ if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) ++ return -EINVAL; ++ ++ return 0; ++} ++ + typedef void (rq_end_io_fn)(struct request *, blk_status_t); + + /* +diff --git a/include/linux/pci.h b/include/linux/pci.h +index a55097b4d9927..4519bd12643f6 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -227,6 +227,8 @@ enum pci_dev_flags { + PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10), + /* Don't use Relaxed Ordering for TLPs directed at this device */ + PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11), ++ /* Device does honor MSI masking despite saying otherwise */ ++ PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12), + }; + + enum pci_irq_reroute_variant { +diff --git a/init/main.c b/init/main.c +index dd26a42e80a87..4fe58ed4aca7b 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -380,6 +380,7 @@ static char * __init xbc_make_cmdline(const char *key) + ret = xbc_snprint_cmdline(new_cmdline, len + 1, root); + if (ret < 0 || ret > len) { + pr_err("Failed to print extra kernel cmdline.\n"); ++ memblock_free(__pa(new_cmdline), len + 1); + return NULL; + } + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index c811519261710..908417736f4e9 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -7036,7 +7036,6 @@ void perf_output_sample(struct perf_output_handle *handle, + static u64 perf_virt_to_phys(u64 virt) + { + u64 phys_addr = 0; +- struct page *p = NULL; + + if (!virt) + return 0; +@@ -7055,14 +7054,15 @@ static u64 perf_virt_to_phys(u64 virt) + * If failed, leave phys_addr as 0. + */ + if (current->mm != NULL) { ++ struct page *p; ++ + pagefault_disable(); +- if (get_user_page_fast_only(virt, 0, &p)) ++ if (get_user_page_fast_only(virt, 0, &p)) { + phys_addr = page_to_phys(p) + virt % PAGE_SIZE; ++ put_page(p); ++ } + pagefault_enable(); + } +- +- if (p) +- put_page(p); + } + + return phys_addr; +diff --git a/scripts/lld-version.sh b/scripts/lld-version.sh +index d70edb4d8a4f2..f1eeee450a23c 100755 +--- a/scripts/lld-version.sh ++++ b/scripts/lld-version.sh +@@ -6,15 +6,32 @@ + # Print the linker version of `ld.lld' in a 5 or 6-digit form + # such as `100001' for ld.lld 10.0.1 etc. + +-linker_string="$($* --version)" ++set -e + +-if ! ( echo $linker_string | grep -q LLD ); then ++# Convert the version string x.y.z to a canonical 5 or 6-digit form. ++get_canonical_version() ++{ ++ IFS=. ++ set -- $1 ++ ++ # If the 2nd or 3rd field is missing, fill it with a zero. ++ echo $((10000 * $1 + 100 * ${2:-0} + ${3:-0})) ++} ++ ++# Get the first line of the --version output. ++IFS=' ++' ++set -- $(LC_ALL=C "$@" --version) ++ ++# Split the line on spaces. ++IFS=' ' ++set -- $1 ++ ++while [ $# -gt 1 -a "$1" != "LLD" ]; do ++ shift ++done ++if [ "$1" = LLD ]; then ++ echo $(get_canonical_version ${2%-*}) ++else + echo 0 +- exit 1 + fi +- +-VERSION=$(echo $linker_string | cut -d ' ' -f 2) +-MAJOR=$(echo $VERSION | cut -d . -f 1) +-MINOR=$(echo $VERSION | cut -d . -f 2) +-PATCHLEVEL=$(echo $VERSION | cut -d . -f 3) +-printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL +diff --git a/security/Kconfig b/security/Kconfig +index 7561f6f99f1d2..0548db16c49dc 100644 +--- a/security/Kconfig ++++ b/security/Kconfig +@@ -191,6 +191,9 @@ config HARDENED_USERCOPY_PAGESPAN + config FORTIFY_SOURCE + bool "Harden common str/mem functions against buffer overflows" + depends on ARCH_HAS_FORTIFY_SOURCE ++ # https://bugs.llvm.org/show_bug.cgi?id=50322 ++ # https://bugs.llvm.org/show_bug.cgi?id=41459 ++ depends on !CC_IS_CLANG + help + Detect overflows of buffers in common string and memory functions + where the compiler can determine and validate the buffer sizes. +diff --git a/tools/testing/selftests/x86/iopl.c b/tools/testing/selftests/x86/iopl.c +index bab2f6e06b63d..7e3e09c1abac6 100644 +--- a/tools/testing/selftests/x86/iopl.c ++++ b/tools/testing/selftests/x86/iopl.c +@@ -85,48 +85,88 @@ static void expect_gp_outb(unsigned short port) + printf("[OK]\toutb to 0x%02hx failed\n", port); + } + +-static bool try_cli(void) ++#define RET_FAULTED 0 ++#define RET_FAIL 1 ++#define RET_EMUL 2 ++ ++static int try_cli(void) + { ++ unsigned long flags; ++ + sethandler(SIGSEGV, sigsegv, SA_RESETHAND); + if (sigsetjmp(jmpbuf, 1) != 0) { +- return false; ++ return RET_FAULTED; + } else { +- asm volatile ("cli"); +- return true; ++ asm volatile("cli; pushf; pop %[flags]" ++ : [flags] "=rm" (flags)); ++ ++ /* X86_FLAGS_IF */ ++ if (!(flags & (1 << 9))) ++ return RET_FAIL; ++ else ++ return RET_EMUL; + } + clearhandler(SIGSEGV); + } + +-static bool try_sti(void) ++static int try_sti(bool irqs_off) + { ++ unsigned long flags; ++ + sethandler(SIGSEGV, sigsegv, SA_RESETHAND); + if (sigsetjmp(jmpbuf, 1) != 0) { +- return false; ++ return RET_FAULTED; + } else { +- asm volatile ("sti"); +- return true; ++ asm volatile("sti; pushf; pop %[flags]" ++ : [flags] "=rm" (flags)); ++ ++ /* X86_FLAGS_IF */ ++ if (irqs_off && (flags & (1 << 9))) ++ return RET_FAIL; ++ else ++ return RET_EMUL; + } + clearhandler(SIGSEGV); + } + +-static void expect_gp_sti(void) ++static void expect_gp_sti(bool irqs_off) + { +- if (try_sti()) { ++ int ret = try_sti(irqs_off); ++ ++ switch (ret) { ++ case RET_FAULTED: ++ printf("[OK]\tSTI faulted\n"); ++ break; ++ case RET_EMUL: ++ printf("[OK]\tSTI NOPped\n"); ++ break; ++ default: + printf("[FAIL]\tSTI worked\n"); + nerrs++; +- } else { +- printf("[OK]\tSTI faulted\n"); + } + } + +-static void expect_gp_cli(void) ++/* ++ * Returns whether it managed to disable interrupts. ++ */ ++static bool test_cli(void) + { +- if (try_cli()) { ++ int ret = try_cli(); ++ ++ switch (ret) { ++ case RET_FAULTED: ++ printf("[OK]\tCLI faulted\n"); ++ break; ++ case RET_EMUL: ++ printf("[OK]\tCLI NOPped\n"); ++ break; ++ default: + printf("[FAIL]\tCLI worked\n"); + nerrs++; +- } else { +- printf("[OK]\tCLI faulted\n"); ++ return true; + } ++ ++ return false; + } + + int main(void) +@@ -152,8 +192,7 @@ int main(void) + } + + /* Make sure that CLI/STI are blocked even with IOPL level 3 */ +- expect_gp_cli(); +- expect_gp_sti(); ++ expect_gp_sti(test_cli()); + expect_ok_outb(0x80); + + /* Establish an I/O bitmap to test the restore */ +@@ -204,8 +243,7 @@ int main(void) + printf("[RUN]\tparent: write to 0x80 (should fail)\n"); + + expect_gp_outb(0x80); +- expect_gp_cli(); +- expect_gp_sti(); ++ expect_gp_sti(test_cli()); + + /* Test the capability checks. */ + printf("\tiopl(3)\n"); |