diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2020-07-30 00:53:34 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2020-07-30 00:53:34 -0700 |
commit | 6848e18857f54f47b24409257a0c3665b4733d87 (patch) | |
tree | ea7b3167620d3f4155e3b96a1a62752f0b87ed47 | |
parent | 42365e4a81888e64540f9932ed00b555e013897e (diff) | |
parent | 62a52f3291d13f398277764de6e4854e18cedfcb (diff) |
Merge 62a52f3291d13f398277764de6e4854e18cedfcb on remote branchLA.UM.8.12.r1-13700-sm8250.0
Change-Id: I105b5b21335ae0139b101a1e9bbc18a79d962260
38 files changed, 514 insertions, 213 deletions
diff --git a/arch/arm64/configs/vendor/kona-perf_defconfig b/arch/arm64/configs/vendor/kona-perf_defconfig index d4c38fbad205..c7909aabb699 100644 --- a/arch/arm64/configs/vendor/kona-perf_defconfig +++ b/arch/arm64/configs/vendor/kona-perf_defconfig @@ -340,6 +340,7 @@ CONFIG_TABLET_USB_GTCO=y CONFIG_TABLET_USB_HANWANG=y CONFIG_TABLET_USB_KBTAB=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_FTS=y CONFIG_INPUT_MISC=y CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_QTI_HAPTICS=y diff --git a/arch/arm64/configs/vendor/kona_defconfig b/arch/arm64/configs/vendor/kona_defconfig index fd023be77f7f..d3c151df020e 100644 --- a/arch/arm64/configs/vendor/kona_defconfig +++ b/arch/arm64/configs/vendor/kona_defconfig @@ -352,6 +352,7 @@ CONFIG_TABLET_USB_GTCO=y CONFIG_TABLET_USB_HANWANG=y CONFIG_TABLET_USB_KBTAB=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_FTS=y CONFIG_INPUT_MISC=y CONFIG_INPUT_QPNP_POWER_ON=y CONFIG_INPUT_QTI_HAPTICS=y diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index c65a8237cf7e..ebba51653546 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -103,6 +103,9 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) { struct stackframe frame; int skip = 0; + long cur_state = 0; + unsigned long cur_sp = 0; + unsigned long cur_fp = 0; pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); @@ -127,6 +130,9 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) */ frame.fp = thread_saved_fp(tsk); frame.pc = thread_saved_pc(tsk); + cur_state = tsk->state; + cur_sp = thread_saved_sp(tsk); + cur_fp = frame.fp; } #ifdef CONFIG_FUNCTION_GRAPH_TRACER frame.graph = tsk->curr_ret_stack; @@ -134,6 +140,23 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) printk("Call trace:\n"); do { + if (tsk != current && (cur_state != tsk->state + /* + * We would not be printing backtrace for the task + * that has changed state from uninterruptible to + * running before hitting the do-while loop but after + * saving the current state. If task is in running + * state before saving the state, then we may print + * wrong call trace or end up in infinite while loop + * if *(fp) and *(fp+8) are same. While the situation + * will stop print when that task schedule out. + */ + || cur_sp != thread_saved_sp(tsk) + || cur_fp != thread_saved_fp(tsk))) { + printk("The task:%s had been rescheduled!\n", + tsk->comm); + break; + } /* skip until specified stack frame */ if (!skip) { dump_backtrace_entry(frame.pc); diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 840117f6f9f3..63deaca35045 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -1560,9 +1560,9 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); init_waitqueue_head(&mhi_cntrl->state_event); - mhi_cntrl->special_wq = alloc_ordered_workqueue("mhi_special_w", + mhi_cntrl->wq = alloc_ordered_workqueue("mhi_w", WQ_MEM_RECLAIM | WQ_HIGHPRI); - if (!mhi_cntrl->special_wq) + if (!mhi_cntrl->wq) goto error_alloc_cmd; INIT_WORK(&mhi_cntrl->special_work, mhi_special_purpose_work); @@ -1688,7 +1688,7 @@ error_add_dev: error_alloc_dev: kfree(mhi_cntrl->mhi_cmd); - destroy_workqueue(mhi_cntrl->special_wq); + destroy_workqueue(mhi_cntrl->wq); error_alloc_cmd: vfree(mhi_cntrl->mhi_chan); diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index c85c2e1fb76f..eaea66209a22 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -1206,19 +1206,21 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, enum MHI_PM_STATE new_state; /* - * Don't process sys error if device support - * rddm since we will be processing rddm ee - * event instead of sys error state change event + * Allow move to SYS_ERROR even if RDDM is + * supported so that core driver is inactive + * with anticipation of an upcoming RDDM event */ - if (mhi_cntrl->ee == MHI_EE_RDDM || - mhi_cntrl->rddm_supported) - break; - - MHI_ERR("MHI system error detected\n"); write_lock_irq(&mhi_cntrl->pm_lock); + /* skip if RDDM event was already processed */ + if (mhi_cntrl->ee == MHI_EE_RDDM) { + write_unlock_irq(&mhi_cntrl->pm_lock); + break; + } new_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_SYS_ERR_DETECT); write_unlock_irq(&mhi_cntrl->pm_lock); + + MHI_ERR("MHI system error detected\n"); if (new_state == MHI_PM_SYS_ERR_DETECT) mhi_process_sys_err(mhi_cntrl); break; @@ -1256,6 +1258,22 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, st = MHI_ST_TRANSITION_MISSION_MODE; break; case MHI_EE_RDDM: + if (mhi_cntrl->ee == MHI_EE_RDDM || + mhi_cntrl->power_down) + break; + + MHI_ERR("RDDM event occurred!\n"); + write_lock_irq(&mhi_cntrl->pm_lock); + mhi_cntrl->ee = MHI_EE_RDDM; + write_unlock_irq(&mhi_cntrl->pm_lock); + + /* notify critical clients */ + mhi_control_error(mhi_cntrl); + + mhi_cntrl->status_cb(mhi_cntrl, + mhi_cntrl->priv_data, + MHI_CB_EE_RDDM); + wake_up_all(&mhi_cntrl->state_event); break; default: MHI_ERR("Unhandled EE event:%s\n", @@ -1659,13 +1677,14 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) write_unlock_irq(&mhi_cntrl->pm_lock); MHI_ERR("RDDM event occurred!\n"); - mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, - MHI_CB_EE_RDDM); - wake_up_all(&mhi_cntrl->state_event); /* notify critical clients with early notifications */ mhi_control_error(mhi_cntrl); + mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, + MHI_CB_EE_RDDM); + wake_up_all(&mhi_cntrl->state_event); + goto exit_intvec; } @@ -1706,7 +1725,7 @@ irqreturn_t mhi_intvec_handlr(int irq_number, void *dev) MHI_VERB("Exit\n"); if (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) - queue_work(mhi_cntrl->special_wq, &mhi_cntrl->special_work); + queue_work(mhi_cntrl->wq, &mhi_cntrl->special_work); return IRQ_WAKE_THREAD; } @@ -1920,7 +1939,8 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl, return 0; error_dec_pendpkt: - atomic_dec(&mhi_cntrl->pending_pkts); + if (in_mission_mode) + atomic_dec(&mhi_cntrl->pending_pkts); error_pm_state: if (!mhi_chan->offload_ch) mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); @@ -2716,8 +2736,11 @@ int mhi_get_remote_time(struct mhi_device *mhi_dev, tsync_node->cb_func = cb_func; tsync_node->mhi_dev = mhi_dev; - if (mhi_tsync->db_response_pending) + if (mhi_tsync->db_response_pending) { + mhi_device_put(mhi_cntrl->mhi_dev, + MHI_VOTE_DEVICE | MHI_VOTE_BUS); goto skip_tsync_db; + } mhi_tsync->int_sequence++; if (mhi_tsync->int_sequence == 0xFFFFFFFF) diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index f9016bb936fc..56da77b64b6e 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -101,8 +101,9 @@ static struct mhi_pm_transitions const mhi_state_transitions[] = { }, { MHI_PM_SYS_ERR_DETECT, - MHI_PM_SYS_ERR_PROCESS | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT | MHI_PM_SHUTDOWN_NO_ACCESS + MHI_PM_DEVICE_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | + MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT | + MHI_PM_SHUTDOWN_NO_ACCESS }, { MHI_PM_SYS_ERR_PROCESS, @@ -785,7 +786,7 @@ int mhi_queue_disable_transition(struct mhi_controller *mhi_cntrl, list_add_tail(&item->node, &mhi_cntrl->transition_list); spin_unlock_irqrestore(&mhi_cntrl->transition_lock, flags); - schedule_work(&mhi_cntrl->st_worker); + queue_work(mhi_cntrl->wq, &mhi_cntrl->st_worker); return 0; } @@ -805,7 +806,7 @@ int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, list_add_tail(&item->node, &mhi_cntrl->transition_list); spin_unlock_irqrestore(&mhi_cntrl->transition_lock, flags); - schedule_work(&mhi_cntrl->st_worker); + queue_work(mhi_cntrl->wq, &mhi_cntrl->st_worker); return 0; } @@ -821,8 +822,7 @@ static void mhi_special_events_pending(struct mhi_controller *mhi_cntrl) spin_lock_bh(&mhi_event->lock); if (ev_ring->rp != mhi_to_virtual(ev_ring, er_ctxt->rp)) { - queue_work(mhi_cntrl->special_wq, - &mhi_cntrl->special_work); + queue_work(mhi_cntrl->wq, &mhi_cntrl->special_work); spin_unlock_bh(&mhi_event->lock); break; } @@ -1497,6 +1497,26 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client) return -EIO; } + if (mhi_cntrl->rddm_supported) { + if (mhi_get_exec_env(mhi_cntrl) == MHI_EE_RDDM && + !mhi_cntrl->power_down) { + mhi_cntrl->ee = MHI_EE_RDDM; + write_unlock_irq(&mhi_cntrl->pm_lock); + + MHI_ERR("RDDM event occurred!\n"); + + /* notify critical clients with early notifications */ + mhi_control_error(mhi_cntrl); + + mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, + MHI_CB_EE_RDDM); + wake_up_all(&mhi_cntrl->state_event); + + tasklet_enable(&mhi_cntrl->mhi_event->task); + goto exit_pm_fast_resume; + } + } + /* restore the states */ mhi_cntrl->pm_state = mhi_cntrl->saved_pm_state; mhi_cntrl->dev_state = mhi_cntrl->saved_dev_state; @@ -1543,6 +1563,7 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client) if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) mhi_timesync_log(mhi_cntrl); +exit_pm_fast_resume: MHI_LOG("Exit with pm_state:%s dev_state:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_STATE_STR(mhi_cntrl->dev_state)); diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c index 94ab96168b41..402fac560963 100644 --- a/drivers/clk/qcom/gdsc-regulator.c +++ b/drivers/clk/qcom/gdsc-regulator.c @@ -577,6 +577,19 @@ static int gdsc_set_mode(struct regulator_dev *rdev, unsigned int mode) */ gdsc_mb(sc); udelay(1); + + /* + * While switching from HW to SW mode, HW may be busy + * updating internal required signals. Polling for PWR_ON + * ensures that the GDSC switches to SW mode before software + * starts to use SW mode. + */ + if (sc->is_gdsc_enabled) { + ret = poll_gdsc_status(sc, ENABLED); + if (ret) + dev_err(&rdev->dev, "%s enable timed out\n", + sc->rdesc.name); + } break; default: ret = -EINVAL; diff --git a/drivers/clk/qcom/npucc-lagoon.c b/drivers/clk/qcom/npucc-lagoon.c index 99c28e682656..bfef188865d3 100644 --- a/drivers/clk/qcom/npucc-lagoon.c +++ b/drivers/clk/qcom/npucc-lagoon.c @@ -184,7 +184,7 @@ static struct clk_alpha_pll npu_cc_pll1 = { /* 250MHz Configuration */ static struct alpha_pll_config npu_q6ss_pll_config = { .l = 0xD, - .cal_l = 0x1E, + .cal_l = 0x3F, .alpha = 0x555, .config_ctl_val = 0x20485699, .config_ctl_hi_val = 0x00002067, @@ -319,12 +319,12 @@ static struct clk_rcg2 npu_cc_xo_clk_src = { }; static const struct freq_tbl ftbl_npu_dsp_core_clk_src[] = { - F(250000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(300000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(400000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(500000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(660000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), - F(800000000, P_NPU_Q6SS_PLL_OUT_MAIN, 1, 0, 0), + F(250000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(300000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(400000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(500000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(660000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), + F(800000000, P_NPU_Q6SS_PLL_OUT_MAIN, 2, 0, 0), { } }; diff --git a/drivers/media/platform/msm/npu/npu_firmware.h b/drivers/media/platform/msm/npu/npu_firmware.h index 3d8537b05790..f807d78a9366 100644 --- a/drivers/media/platform/msm/npu/npu_firmware.h +++ b/drivers/media/platform/msm/npu/npu_firmware.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _NPU_FIRMWARE_H @@ -68,8 +68,8 @@ #define HOST_CTRL_STATUS_IPC_ADDRESS_READY_BIT 0 /* Host has enabled logging during boot */ #define HOST_CTRL_STATUS_BOOT_ENABLE_LOGGING_BIT 1 -/* Host has enabled the clk gating of CAL during boot */ -#define HOST_CTRL_STATUS_BOOT_ENABLE_CLK_GATE_BIT 2 +/* Host has disabled the clk gating of CAL during boot */ +#define HOST_CTRL_STATUS_BOOT_DISABLE_CLK_GATE_BIT 2 /* Host requests to pause fw during boot up */ #define HOST_CTRL_STATUS_FW_PAUSE 3 /* Host requests to disable watchdog */ @@ -80,8 +80,8 @@ (1 << HOST_CTRL_STATUS_IPC_ADDRESS_READY_BIT) #define HOST_CTRL_STATUS_BOOT_ENABLE_LOGGING_VAL \ (1 << HOST_CTRL_STATUS_BOOT_ENABLE_LOGGING_BIT) -#define HOST_CTRL_STATUS_BOOT_ENABLE_CLK_GATE_VAL \ - (1 << HOST_CTRL_STATUS_BOOT_ENABLE_CLK_GATE_BIT) +#define HOST_CTRL_STATUS_BOOT_DISABLE_CLK_GATE_VAL \ + (1 << HOST_CTRL_STATUS_BOOT_DISABLE_CLK_GATE_BIT) #define HOST_CTRL_STATUS_FW_PAUSE_VAL \ (1 << HOST_CTRL_STATUS_FW_PAUSE) #define HOST_CTRL_STATUS_DISABLE_WDOG_VAL \ diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index d497a7f77e5e..dea1349f63e1 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -313,6 +313,7 @@ static int enable_fw_nolock(struct npu_device *npu_dev) { struct npu_host_ctx *host_ctx = &npu_dev->host_ctx; int ret = 0; + uint32_t reg_val; if (host_ctx->fw_state == FW_UNLOADED) { ret = load_fw_nolock(npu_dev, @@ -350,6 +351,26 @@ static int enable_fw_nolock(struct npu_device *npu_dev) goto enable_sys_cache_fail; } + /* Clear control/status registers */ + REGW(npu_dev, REG_NPU_FW_CTRL_STATUS, 0x0); + REGW(npu_dev, REG_NPU_HOST_CTRL_VALUE, 0x0); + REGW(npu_dev, REG_FW_TO_HOST_EVENT, 0x0); + + NPU_DBG("fw_dbg_mode %x\n", host_ctx->fw_dbg_mode); + reg_val = 0; + if (host_ctx->fw_dbg_mode & FW_DBG_MODE_PAUSE) + reg_val |= HOST_CTRL_STATUS_FW_PAUSE_VAL; + + if (host_ctx->fw_dbg_mode & FW_DBG_DISABLE_WDOG) + reg_val |= HOST_CTRL_STATUS_DISABLE_WDOG_VAL; + + if (!npu_hw_clk_gating_enabled()) + reg_val |= HOST_CTRL_STATUS_BOOT_DISABLE_CLK_GATE_VAL; + + REGW(npu_dev, REG_NPU_HOST_CTRL_STATUS, reg_val); + /* Read back to flush all registers for fw to read */ + REGR(npu_dev, REG_NPU_HOST_CTRL_STATUS); + /* Initialize the host side IPC before fw boots up */ npu_host_ipc_pre_init(npu_dev); npu_host_ipc_post_init(npu_dev); @@ -626,8 +647,8 @@ static int npu_notifier_cb(struct notifier_block *this, unsigned long code, if (host_ctx->fw_dbg_mode & FW_DBG_DISABLE_WDOG) reg_val |= HOST_CTRL_STATUS_DISABLE_WDOG_VAL; - if (npu_hw_clk_gating_enabled()) - reg_val |= HOST_CTRL_STATUS_BOOT_ENABLE_CLK_GATE_VAL; + if (!npu_hw_clk_gating_enabled()) + reg_val |= HOST_CTRL_STATUS_BOOT_DISABLE_CLK_GATE_VAL; REGW(npu_dev, REG_NPU_HOST_CTRL_STATUS, reg_val); /* Read back to flush all registers for fw to read */ diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index de7bf65459dd..c300976b0153 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -387,7 +387,6 @@ int mmc_add_card(struct mmc_card *card) return ret; mmc_card_set_present(card); - device_enable_async_suspend(&card->dev); return 0; } diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 71b56258feae..8e70097921e7 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1300,7 +1300,7 @@ static ssize_t store_mask_and_match(struct device *dev, unsigned long value; char *token; int i = 0; - u32 mask, match, bit_shift, testbus; + u32 mask = 0, match = 0, bit_shift = 0, testbus = 0; char *temp = (char *)buf; diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index bde75836564f..fc46f5b127cc 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -200,9 +200,10 @@ int cnss_get_platform_cap(struct device *dev, struct cnss_platform_cap *cap) if (!plat_priv) return -ENODEV; - if (cap) - *cap = plat_priv->cap; + if (!cap) + return -EINVAL; + *cap = plat_priv->cap; cnss_pr_dbg("Platform cap_flag is 0x%x\n", cap->cap_flag); return 0; diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 391ff6f0325c..523459a656b3 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -768,56 +768,42 @@ static void gsi_handle_general(int ee) GSI_EE_n_CNTXT_GSI_IRQ_CLR_OFFS(ee)); } -#define GSI_ISR_MAX_ITER 50 - static void gsi_handle_irq(void) { uint32_t type; int ee = gsi_ctx->per.ee; - unsigned long cnt = 0; - while (1) { - if (!gsi_ctx->per.clk_status_cb()) - break; - type = gsi_readl(gsi_ctx->base + - GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(ee)); + if (!gsi_ctx->per.clk_status_cb()) + return; - if (!type) - break; + type = gsi_readl(gsi_ctx->base + + GSI_EE_n_CNTXT_TYPE_IRQ_OFFS(ee)); - GSIDBG_LOW("type 0x%x\n", type); + if (!type) + return; - if (type & GSI_EE_n_CNTXT_TYPE_IRQ_CH_CTRL_BMSK) - gsi_handle_ch_ctrl(ee); + GSIDBG_LOW("type 0x%x\n", type); - if (type & GSI_EE_n_CNTXT_TYPE_IRQ_EV_CTRL_BMSK) - gsi_handle_ev_ctrl(ee); + if (type & GSI_EE_n_CNTXT_TYPE_IRQ_CH_CTRL_BMSK) + gsi_handle_ch_ctrl(ee); - if (type & GSI_EE_n_CNTXT_TYPE_IRQ_GLOB_EE_BMSK) - gsi_handle_glob_ee(ee); + if (type & GSI_EE_n_CNTXT_TYPE_IRQ_EV_CTRL_BMSK) + gsi_handle_ev_ctrl(ee); - if (type & GSI_EE_n_CNTXT_TYPE_IRQ_IEOB_BMSK) - gsi_handle_ieob(ee); + if (type & GSI_EE_n_CNTXT_TYPE_IRQ_GLOB_EE_BMSK) + gsi_handle_glob_ee(ee); - if (type & GSI_EE_n_CNTXT_TYPE_IRQ_INTER_EE_CH_CTRL_BMSK) - gsi_handle_inter_ee_ch_ctrl(ee); + if (type & GSI_EE_n_CNTXT_TYPE_IRQ_IEOB_BMSK) + gsi_handle_ieob(ee); - if (type & GSI_EE_n_CNTXT_TYPE_IRQ_INTER_EE_EV_CTRL_BMSK) - gsi_handle_inter_ee_ev_ctrl(ee); + if (type & GSI_EE_n_CNTXT_TYPE_IRQ_INTER_EE_CH_CTRL_BMSK) + gsi_handle_inter_ee_ch_ctrl(ee); - if (type & GSI_EE_n_CNTXT_TYPE_IRQ_GENERAL_BMSK) - gsi_handle_general(ee); + if (type & GSI_EE_n_CNTXT_TYPE_IRQ_INTER_EE_EV_CTRL_BMSK) + gsi_handle_inter_ee_ev_ctrl(ee); - if (unlikely(++cnt > GSI_ISR_MAX_ITER)) { - /* - * Max number of spurious interrupts from hardware. - * Unexpected hardware state. - */ - GSIERR("Too many spurious interrupt from GSI HW\n"); - GSI_ASSERT(); - } - - } + if (type & GSI_EE_n_CNTXT_TYPE_IRQ_GENERAL_BMSK) + gsi_handle_general(ee); } static irqreturn_t gsi_isr(int irq, void *ctxt) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c index 439c8f95732e..e5be65538b77 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mpm.c @@ -732,7 +732,6 @@ static void ipa_mpm_smmu_unmap(dma_addr_t carved_iova, int sz, int dir, if (carved_iova <= 0) { IPA_MPM_ERR("carved_iova is zero/negative\n"); - WARN_ON(1); return; } @@ -1568,9 +1567,8 @@ static int ipa_mpm_vote_unvote_pcie_clk(enum ipa_mpm_clk_vote_type vote, if ((atomic_read( &ipa_mpm_ctx->md[probe_id].clk_cnt.pcie_clk_cnt) == 0)) { - IPA_MPM_DBG("probe_id %d PCIE clock already devoted\n", + IPA_MPM_ERR("probe_id %d PCIE clock already devoted\n", probe_id); - WARN_ON(1); *is_acted = true; return 0; } @@ -1606,9 +1604,8 @@ static void ipa_mpm_vote_unvote_ipa_clk(enum ipa_mpm_clk_vote_type vote, if ((atomic_read (&ipa_mpm_ctx->md[probe_id].clk_cnt.ipa_clk_cnt) == 0)) { - IPA_MPM_DBG("probe_id %d IPA clock count < 0\n", + IPA_MPM_ERR("probe_id %d IPA clock count < 0\n", probe_id); - WARN_ON(1); return; } IPA_ACTIVE_CLIENTS_DEC_SPECIAL(ipa_mpm_mhip_chan_str[probe_id]); @@ -2363,7 +2360,6 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev, ret = mhi_prepare_for_transfer(ipa_mpm_ctx->md[probe_id].mhi_dev); if (ret) { IPA_MPM_ERR("mhi_prepare_for_transfer failed %d\n", ret); - WARN_ON(1); /* * WA to handle prepare_for_tx failures. * Though prepare for transfer fails, indicate success @@ -3534,8 +3530,9 @@ int ipa3_qmi_reg_dereg_for_bw(bool bw_reg, int bw_reg_dereg_type) } IPA_MPM_DBG("QMI BW regst success from %d", ipa_mpm_ctx->bw_reg_dereg_cache[ - ipa_mpm_ctx->cache_index - - 1].bw_reg_dereg_type); + (ipa_mpm_ctx->cache_index - + 1) % IPA_MAX_BW_REG_DEREG_CACHE]. + bw_reg_dereg_type); } else { IPA_MPM_DBG("bw_change to %d no-op, teth_count = %d", bw_reg, @@ -3556,8 +3553,9 @@ int ipa3_qmi_reg_dereg_for_bw(bool bw_reg, int bw_reg_dereg_type) } IPA_MPM_DBG("QMI BW De-regst success %d", ipa_mpm_ctx->bw_reg_dereg_cache[ - ipa_mpm_ctx->cache_index - - 1].bw_reg_dereg_type); + (ipa_mpm_ctx->cache_index - + 1) % IPA_MAX_BW_REG_DEREG_CACHE]. + bw_reg_dereg_type); } else { IPA_MPM_DBG("bw_change to %d no-op, teth_count = %d", bw_reg, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index eb453fded02b..c1e3735827fc 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -775,6 +775,44 @@ int ipa3_qmi_filter_request_send(struct ipa_install_fltr_rule_req_msg_v01 *req) resp.resp.error, "ipa_install_filter"); } +static int ipa3_qmi_filter_request_ex_calc_length( + struct ipa_install_fltr_rule_req_ex_msg_v01 *req) +{ + int len = 0; + + /* caller should validate and send the req */ + /* instead of sending max length,the approximate length is calculated */ + len += ((sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01)) - + (QMI_IPA_MAX_FILTERS_EX_V01 * + sizeof(struct ipa_filter_spec_ex_type_v01) - + QMI_IPA_MAX_FILTERS_EX_V01 * sizeof(uint32_t)) - + (QMI_IPA_MAX_FILTERS_V01 * + sizeof(struct ipa_filter_spec_ex2_type_v01))); + + if (req->filter_spec_ex_list_valid && + req->filter_spec_ex_list_len > 0) { + len += sizeof(struct ipa_filter_spec_ex_type_v01)* + req->filter_spec_ex_list_len; + } + if (req->xlat_filter_indices_list_valid && + req->xlat_filter_indices_list_len > 0) { + len += sizeof(uint32_t)*req->xlat_filter_indices_list_len; + } + + if (req->filter_spec_ex2_list_valid && + req->filter_spec_ex2_list_len > 0) { + len += sizeof(struct ipa_filter_spec_ex2_type_v01)* + req->filter_spec_ex2_list_len; + } + + if (req->ul_firewall_indices_list_valid && + req->ul_firewall_indices_list_len > 0) { + len += sizeof(uint32_t)*req->ul_firewall_indices_list_len; + } + + return len; +} + /* sending filter-install-request to modem*/ int ipa3_qmi_filter_request_ex_send( struct ipa_install_fltr_rule_req_ex_msg_v01 *req) @@ -840,8 +878,9 @@ int ipa3_qmi_filter_request_ex_send( } mutex_unlock(&ipa3_qmi_lock); - req_desc.max_msg_len = - QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_MAX_MSG_LEN_V01; + req_desc.max_msg_len = ipa3_qmi_filter_request_ex_calc_length(req); + IPAWANDBG("QMI send request length = %d\n", req_desc.max_msg_len); + req_desc.msg_id = QMI_IPA_INSTALL_FILTER_RULE_EX_REQ_V01; req_desc.ei_array = ipa3_install_fltr_rule_req_ex_msg_data_v01_ei; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index a3adc694e762..95b059b8eb5f 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -2068,6 +2068,12 @@ static const struct ipa_ep_configuration ipa3_ep_mapping IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 12, 4, 4, 4, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY} }, + [IPA_4_2][IPA_CLIENT_ODL_DPL_CONS] = { + true, IPA_v4_2_GROUP_UL_DL, + false, + IPA_DPS_HPS_SEQ_TYPE_INVALID, + QMB_MASTER_SELECT_DDR, + { 13, 10, 6, 6, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY} }, [IPA_4_2][IPA_CLIENT_APPS_LAN_CONS] = { true, IPA_v4_2_GROUP_UL_DL, false, @@ -2092,12 +2098,6 @@ static const struct ipa_ep_configuration ipa3_ep_mapping IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 10, 2, 6, 6, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY} }, - [IPA_4_2][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = { - true, IPA_v4_2_GROUP_UL_DL, - false, - IPA_DPS_HPS_SEQ_TYPE_INVALID, - QMB_MASTER_SELECT_DDR, - { 13, 4, 6, 6, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY} }, [IPA_4_2][IPA_CLIENT_ETHERNET_CONS] = { true, IPA_v4_2_GROUP_UL_DL, false, diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c index bad741fa926f..4089a21e0e3c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. */ #include <linux/init.h> @@ -96,7 +96,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_install_fltr_rule_req_msg_v01); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -117,7 +117,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE_EX :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -138,7 +138,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_OFFLOAD_CONNECTION :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_add_offload_connection_req_msg_v01); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -160,7 +160,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_RMV_OFFLOAD_CONNECTION :>>>\n", DRIVER_NAME); pyld_sz = rmv_offload_req__msg_size; - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -183,7 +183,7 @@ static long ipa3_wan_ioctl(struct file *filp, DRIVER_NAME); pyld_sz = sizeof(struct ipa_configure_ul_firewall_rules_req_msg_v01); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -205,7 +205,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_ADD_FLT_RULE_INDEX :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct ipa_fltr_installed_notif_req_msg_v01); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -226,7 +226,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG("device %s got WAN_IOC_VOTE_FOR_BW_MBPS :>>>\n", DRIVER_NAME); pyld_sz = sizeof(uint32_t); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -245,7 +245,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_POLL_TETHERING_STATS: IPAWANDBG_LOW("got WAN_IOCTL_POLL_TETHERING_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_poll_tethering_stats); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -266,7 +266,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG_LOW("device %s got WAN_IOCTL_SET_DATA_QUOTA :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct wan_ioctl_set_data_quota); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -290,7 +290,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_SET_TETHER_CLIENT_PIPE: IPAWANDBG_LOW("got WAN_IOC_SET_TETHER_CLIENT_PIPE :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_set_tether_client_pipe); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -306,7 +306,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_QUERY_TETHER_STATS: IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_query_tether_stats); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -328,7 +328,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_QUERY_TETHER_STATS_ALL: IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS_ALL :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_query_tether_stats_all); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -351,7 +351,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG_LOW("device %s got WAN_IOC_RESET_TETHER_STATS :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct wan_ioctl_reset_tether_stats); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -369,7 +369,7 @@ static long ipa3_wan_ioctl(struct file *filp, IPAWANDBG_LOW("device %s got WAN_IOC_NOTIFY_WAN_STATE :>>>\n", DRIVER_NAME); pyld_sz = sizeof(struct wan_ioctl_notify_wan_state); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -391,7 +391,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_ENABLE_PER_CLIENT_STATS: IPAWANDBG_LOW("got WAN_IOC_ENABLE_PER_CLIENT_STATS :>>>\n"); pyld_sz = sizeof(bool); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -406,7 +406,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_QUERY_PER_CLIENT_STATS: IPAWANDBG_LOW("got WAN_IOC_QUERY_PER_CLIENT_STATS :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_query_per_client_stats); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -428,7 +428,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_SET_LAN_CLIENT_INFO: IPAWANDBG_LOW("got WAN_IOC_SET_LAN_CLIENT_INFO :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_lan_client_info); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -444,7 +444,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_CLEAR_LAN_CLIENT_INFO: IPAWANDBG_LOW("got WAN_IOC_CLEAR_LAN_CLIENT_INFO :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_lan_client_info); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -461,7 +461,7 @@ static long ipa3_wan_ioctl(struct file *filp, case WAN_IOC_SEND_LAN_CLIENT_MSG: IPAWANDBG_LOW("got WAN_IOC_SEND_LAN_CLIENT_MSG :>>>\n"); pyld_sz = sizeof(struct wan_ioctl_send_lan_client_msg); - param = memdup_user((const void __user *)arg, pyld_sz); + param = vmemdup_user((const void __user *)arg, pyld_sz); if (IS_ERR(param)) { retval = PTR_ERR(param); break; @@ -479,7 +479,7 @@ static long ipa3_wan_ioctl(struct file *filp, retval = -ENOTTY; } if (!IS_ERR(param)) - kfree(param); + kvfree(param); return retval; } diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 8a119caac50d..d47e4357de03 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -193,7 +193,8 @@ static int cp_get_parallel_mode(struct pl_data *chip, int mode) static int get_adapter_icl_based_ilim(struct pl_data *chip) { - int main_icl, adapter_icl = -EINVAL, rc = -EINVAL, final_icl = -EINVAL; + int main_icl = -EINVAL, adapter_icl = -EINVAL, final_icl = -EINVAL; + int rc = -EINVAL; union power_supply_propval pval = {0, }; rc = power_supply_get_property(chip->usb_psy, diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c index c17c61e382a2..84e6d0cbe52e 100644 --- a/drivers/power/supply/qcom/fg-alg.c +++ b/drivers/power/supply/qcom/fg-alg.c @@ -1545,15 +1545,18 @@ int ttf_get_time_to_empty(struct ttf *ttf, int *val) return 0; } + mutex_lock(&ttf->lock); rc = ttf_circ_buf_median(&ttf->ibatt, &ibatt_avg); if (rc < 0) { /* try to get instantaneous current */ rc = ttf->get_ttf_param(ttf->data, TTF_IBAT, &ibatt_avg); if (rc < 0) { pr_err("failed to get battery current, rc=%d\n", rc); + mutex_unlock(&ttf->lock); return rc; } } + mutex_unlock(&ttf->lock); ibatt_avg /= MILLI_UNIT; /* clamp ibatt_avg to 100mA */ diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index e61ff4b8823a..cbd823800321 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -4219,7 +4219,7 @@ static int qg_parse_dt(struct qpnp_qg *chip) if (rc < 0) chip->dt.rbat_conn_mohm = 0; else - chip->dt.rbat_conn_mohm = temp; + chip->dt.rbat_conn_mohm = (int)temp; /* esr */ chip->dt.esr_disable = of_property_read_bool(node, diff --git a/drivers/power/supply/qcom/smb1398-charger.c b/drivers/power/supply/qcom/smb1398-charger.c index c53942003ad8..35e099d7c94e 100644 --- a/drivers/power/supply/qcom/smb1398-charger.c +++ b/drivers/power/supply/qcom/smb1398-charger.c @@ -92,6 +92,7 @@ #define MISC_CFG0_REG 0x2634 #define DIS_SYNC_DRV_BIT BIT(5) #define SW_EN_SWITCHER_BIT BIT(3) +#define CFG_DIS_FPF_IREV_BIT BIT(1) #define MISC_CFG1_REG 0x2635 #define MISC_CFG1_MASK GENMASK(7, 0) @@ -1985,6 +1986,14 @@ static int smb1398_div2_cp_hw_init(struct smb1398_chip *chip) return rc; } + /* Do not disable FP_FET during IREV conditions */ + rc = smb1398_masked_write(chip, MISC_CFG0_REG, CFG_DIS_FPF_IREV_BIT, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set CFG_DIS_FPF_IREV_BIT, rc=%d\n", + rc); + return rc; + } + /* switcher enable controlled by register */ rc = smb1398_masked_write(chip, MISC_CFG0_REG, SW_EN_SWITCHER_BIT, SW_EN_SWITCHER_BIT); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 3d577e259e91..6ad7d21da479 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -474,6 +474,14 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_set_alarm); +static void rtc_alarm_disable(struct rtc_device *rtc) +{ + if (!rtc->ops || !rtc->ops->alarm_irq_enable) + return; + + rtc->ops->alarm_irq_enable(rtc->dev.parent, false); +} + /* Called once per device from rtc_device_register */ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { @@ -502,7 +510,11 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) rtc->aie_timer.enabled = 1; timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); trace_rtc_timer_enqueue(&rtc->aie_timer); + } else if (alarm->enabled && (rtc_tm_to_ktime(now) >= + rtc->aie_timer.node.expires)){ + rtc_alarm_disable(rtc); } + mutex_unlock(&rtc->ops_lock); return err; } @@ -836,15 +848,6 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) return 0; } -static void rtc_alarm_disable(struct rtc_device *rtc) -{ - if (!rtc->ops || !rtc->ops->alarm_irq_enable) - return; - - rtc->ops->alarm_irq_enable(rtc->dev.parent, false); - trace_rtc_alarm_irq_enable(0, 0); -} - /** * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue * @rtc rtc device diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 9f8cbbd81ba1..d38f38ddb2a3 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -22,6 +22,7 @@ /* RTC_CTRL register bit fields */ #define PM8xxx_RTC_ENABLE BIT(7) #define PM8xxx_RTC_ALARM_CLEAR BIT(0) +#define PM8xxx_RTC_ALARM_ENABLE BIT(7) #define NUM_8_BIT_RTC_REGS 0x4 @@ -297,6 +298,14 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) alarm->time.tm_sec, alarm->time.tm_mday, alarm->time.tm_mon, alarm->time.tm_year); + rc = regmap_bulk_read(rtc_dd->regmap, regs->alarm_ctrl, value, 1); + if (rc) { + dev_err(dev, "Read from ALARM CTRL1 failed\n"); + return rc; + } + + alarm->enabled = !!(value[0] & PM8xxx_RTC_ALARM_ENABLE); + return 0; } diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 89cc15b75673..d1e90f5e99a4 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2237,12 +2237,12 @@ start: * work and to enable clocks. */ case CLKS_OFF: - ufshcd_scsi_block_requests(hba); hba->clk_gating.state = REQ_CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - queue_work(hba->clk_gating.clk_gating_workq, - &hba->clk_gating.ungate_work); + if (queue_work(hba->clk_gating.clk_gating_workq, + &hba->clk_gating.ungate_work)) + ufshcd_scsi_block_requests(hba); /* * fall through to check if we should wait for this * work to be done or not. @@ -10559,11 +10559,16 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) * we can proceed after checking the link and * dev state. */ - if ((host_byte(ret) == DID_TIME_OUT) && - ufshcd_is_ufs_dev_active(hba) && + if (ufshcd_is_ufs_dev_active(hba) && ufshcd_is_link_active(hba)) ret = 0; - else + + else if ((work_pending(&hba->eh_work)) || + ufshcd_eh_in_progress(hba)) { + flush_work(&hba->eh_work); + ret = 0; + } + if (ret) goto set_old_link_state; } } diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 84934eb3b548..1b3dc0d0d847 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1842,10 +1842,9 @@ int icnss_unregister_driver(struct icnss_driver_ops *ops) icnss_pr_dbg("Unregistering driver, state: 0x%lx\n", penv->state); - if (!penv->ops || (!test_bit(ICNSS_DRIVER_PROBED, &penv->state))) { - icnss_pr_err("Driver not registered/probed\n"); + if (!penv->ops) { + icnss_pr_err("Driver not registered\n"); ret = -ENOENT; - penv->ops = NULL; goto out; } @@ -2291,6 +2290,9 @@ int icnss_trigger_recovery(struct device *dev) if (!ret) set_bit(ICNSS_HOST_TRIGGERED_PDR, &priv->state); + icnss_pr_warn("PD restart request completed, ret: %d state: 0x%lx\n", + ret, priv->state); + out: return ret; } diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index e35111f3c164..f5a38dd0d794 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -2472,6 +2472,9 @@ int icnss_trigger_recovery(struct device *dev) if (!ret) set_bit(ICNSS_HOST_TRIGGERED_PDR, &priv->state); + icnss_pr_warn("PD restart request completed, ret: %d state: 0x%lx\n", + ret, priv->state); + out: return ret; } diff --git a/drivers/soc/qcom/qmi_rmnet.c b/drivers/soc/qcom/qmi_rmnet.c index d88d41d04f3e..039b36ff5d39 100644 --- a/drivers/soc/qcom/qmi_rmnet.c +++ b/drivers/soc/qcom/qmi_rmnet.c @@ -9,6 +9,7 @@ #include <linux/rtnetlink.h> #include <uapi/linux/rtnetlink.h> #include <net/pkt_sched.h> +#include <net/tcp.h> #include "qmi_rmnet_i.h" #include <trace/events/dfc.h> #include <linux/ip.h> @@ -868,16 +869,14 @@ void qmi_rmnet_burst_fc_check(struct net_device *dev, } EXPORT_SYMBOL(qmi_rmnet_burst_fc_check); -static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb) +static bool _qmi_rmnet_is_tcp_ack(struct sk_buff *skb) { - unsigned int len = skb->len; - switch (skb->protocol) { /* TCPv4 ACKs */ case htons(ETH_P_IP): if ((ip_hdr(skb)->protocol == IPPROTO_TCP) && - (ip_hdr(skb)->ihl == 5) && - (len == 40 || len == 52) && + (ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2) == + tcp_hdr(skb)->doff << 2) && ((tcp_flag_word(tcp_hdr(skb)) & cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK)) return true; @@ -886,7 +885,8 @@ static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb) /* TCPv6 ACKs */ case htons(ETH_P_IPV6): if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) && - (len == 60 || len == 72) && + (ntohs(ipv6_hdr(skb)->payload_len) == + (tcp_hdr(skb)->doff) << 2) && ((tcp_flag_word(tcp_hdr(skb)) & cpu_to_be32(0x00FF0000)) == TCP_FLAG_ACK)) return true; @@ -896,6 +896,19 @@ static bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb) return false; } +static inline bool qmi_rmnet_is_tcp_ack(struct sk_buff *skb) +{ + /* Locally generated TCP acks */ + if (skb_is_tcp_pure_ack(skb)) + return true; + + /* Forwarded */ + if (unlikely(_qmi_rmnet_is_tcp_ack(skb))) + return true; + + return false; +} + static int qmi_rmnet_get_queue_sa(struct qos_info *qos, struct sk_buff *skb) { struct rmnet_flow_map *itm; diff --git a/drivers/thermal/qcom/qmi_sensors.c b/drivers/thermal/qcom/qmi_sensors.c index 67c6af50452d..97c1467c65fa 100644 --- a/drivers/thermal/qcom/qmi_sensors.c +++ b/drivers/thermal/qcom/qmi_sensors.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__ @@ -56,6 +56,9 @@ enum qmi_ts_sensor { QMI_SYS_THERM1, QMI_SYS_THERM2, QMI_TS_TSENS_1, + QMI_TS_BEAMER_W_THERM, + QMI_TS_BEAMER_N_THERM, + QMI_TS_BEAMER_E_THERM, QMI_TS_MAX_NR }; @@ -113,6 +116,9 @@ static char sensor_clients[QMI_TS_MAX_NR][QMI_CLIENT_NAME_LENGTH] = { {"sys_therm1"}, {"sys_therm2"}, {"modem_tsens1"}, + {"BEAMER_W_THERM"}, + {"BEAMER_N_THERM"}, + {"BEAMER_E_THERM"}, }; static int32_t encode_qmi(int32_t val) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index ab18bdc7b6d3..0983b605e4c5 100755 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1396,26 +1396,6 @@ static void msm_geni_serial_start_rx(struct uart_port *uport) start_rx_sequencer(&port->uport); } - -static void msm_geni_serial_rx_fsm_rst(struct uart_port *uport) -{ - unsigned int rx_irq_en; - int done = 0; - int tries = 0; - - rx_irq_en = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_EN); - geni_write_reg_nolog(0, uport->membase, SE_DMA_RX_IRQ_EN_SET); - geni_write_reg_nolog(1, uport->membase, SE_DMA_RX_FSM_RST); - do { - done = msm_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT, - RX_RESET_DONE, true); - tries++; - } while (!done && tries < 5); - geni_write_reg_nolog(RX_DMA_DONE | RX_RESET_DONE, uport->membase, - SE_DMA_RX_IRQ_CLR); - geni_write_reg_nolog(rx_irq_en, uport->membase, SE_DMA_RX_IRQ_EN_SET); -} - static void msm_geni_serial_set_manual_flow(bool enable, struct msm_geni_serial_port *port) { @@ -1463,7 +1443,7 @@ static void stop_rx_sequencer(struct uart_port *uport) IPC_LOG_MSG(port->ipc_log_misc, "%s: RX is Inactive, geni_sts: 0x%x\n", __func__, geni_status); - goto exit_rx_seq; + return; } port->s_cmd_done = false; @@ -1522,15 +1502,25 @@ static void stop_rx_sequencer(struct uart_port *uport) IPC_LOG_MSG(port->console_log, "%s abort fail 0x%x\n", __func__, geni_status); } + + if (port->xfer_mode == SE_DMA) { + port->s_cmd_done = false; + reinit_completion(&port->s_cmd_timeout); + geni_write_reg_nolog(1, uport->membase, + SE_DMA_RX_FSM_RST); + + timeout = geni_wait_for_cmd_done(uport, + is_irq_masked); + if (timeout) + IPC_LOG_MSG(port->ipc_log_misc, + "%s: rx fsm reset failed\n", __func__); + } } /* Enable the interrupts once the cancel operation is done. */ msm_geni_serial_enable_interrupts(uport); port->s_cmd = false; exit_rx_seq: - if (port->xfer_mode == SE_DMA && port->rx_dma) - msm_geni_serial_rx_fsm_rst(uport); - geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, "%s: End 0x%x\n", __func__, geni_status); diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c index 0171a2ab3672..cf13a8bb6167 100644 --- a/drivers/usb/phy/phy-msm-qusb-v2.c +++ b/drivers/usb/phy/phy-msm-qusb-v2.c @@ -54,6 +54,10 @@ #define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ #define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ +#define QUSB2PHY_REFGEN_VOL_MIN 1200000 /* uV */ +#define QUSB2PHY_REFGEN_VOL_MAX 1200000 /* uV */ +#define QUSB2PHY_REFGEN_HPM_LOAD 30000 /* uA */ + #define LINESTATE_DP BIT(0) #define LINESTATE_DM BIT(1) @@ -106,6 +110,7 @@ struct qusb_phy { struct regulator *vdd; struct regulator *vdda33; struct regulator *vdda18; + struct regulator *refgen; int vdd_levels[3]; /* none, low, high */ int init_seq_len; int *qusb_phy_init_seq; @@ -193,6 +198,24 @@ static int qusb_phy_disable_power(struct qusb_phy *qphy) dev_dbg(qphy->phy.dev, "%s:req to turn off regulators\n", __func__); + ret = regulator_disable(qphy->refgen); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable refgen:%d\n", ret); + + if (!regulator_is_enabled(qphy->refgen)) { + ret = regulator_set_voltage(qphy->refgen, 0, + QUSB2PHY_REFGEN_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for refgen:%d\n", + ret); + + ret = regulator_set_load(qphy->refgen, 0); + if (ret < 0) + dev_err(qphy->phy.dev, + "Unable to set (0) HPM of refgen\n"); + } + ret = regulator_disable(qphy->vdda33); if (ret) dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret); @@ -309,12 +332,47 @@ static int qusb_phy_enable_power(struct qusb_phy *qphy) goto unset_vdd33; } + ret = regulator_set_load(qphy->refgen, QUSB2PHY_REFGEN_HPM_LOAD); + if (ret < 0) { + dev_err(qphy->phy.dev, "Unable to set HPM of refgen:%d\n", ret); + goto disable_vdd33; + } + + ret = regulator_set_voltage(qphy->refgen, QUSB2PHY_REFGEN_VOL_MIN, + QUSB2PHY_REFGEN_VOL_MAX); + if (ret) { + dev_err(qphy->phy.dev, + "Unable to set voltage for refgen:%d\n", ret); + goto put_refgen_lpm; + } + + ret = regulator_enable(qphy->refgen); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable refgen\n"); + goto unset_refgen; + } pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__); mutex_unlock(&qphy->lock); return ret; +unset_refgen: + ret = regulator_set_voltage(qphy->refgen, 0, QUSB2PHY_REFGEN_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for refgen:%d\n", ret); + +put_refgen_lpm: + ret = regulator_set_load(qphy->refgen, 0); + if (ret < 0) + dev_err(qphy->phy.dev, "Unable to set (0) HPM of refgen\n"); + +disable_vdd33: + ret = regulator_disable(qphy->vdda33); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret); + unset_vdd33: ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX); if (ret) @@ -963,6 +1021,37 @@ create_err: return ret; } +static int qusb2_get_regulators(struct qusb_phy *qphy) +{ + struct device *dev = qphy->phy.dev; + + qphy->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(qphy->vdd)) { + dev_err(dev, "unable to get vdd supply\n"); + return PTR_ERR(qphy->vdd); + } + + qphy->vdda33 = devm_regulator_get(dev, "vdda33"); + if (IS_ERR(qphy->vdda33)) { + dev_err(dev, "unable to get vdda33 supply\n"); + return PTR_ERR(qphy->vdda33); + } + + qphy->vdda18 = devm_regulator_get(dev, "vdda18"); + if (IS_ERR(qphy->vdda18)) { + dev_err(dev, "unable to get vdda18 supply\n"); + return PTR_ERR(qphy->vdda18); + } + + qphy->refgen = devm_regulator_get(dev, "refgen"); + if (IS_ERR(qphy->refgen)) { + dev_err(dev, "unable to get refgen supply\n"); + return PTR_ERR(qphy->refgen); + } + + return 0; +} + static int qusb_phy_probe(struct platform_device *pdev) { struct qusb_phy *qphy; @@ -1216,23 +1305,9 @@ static int qusb_phy_probe(struct platform_device *pdev) return ret; } - qphy->vdd = devm_regulator_get(dev, "vdd"); - if (IS_ERR(qphy->vdd)) { - dev_err(dev, "unable to get vdd supply\n"); - return PTR_ERR(qphy->vdd); - } - - qphy->vdda33 = devm_regulator_get(dev, "vdda33"); - if (IS_ERR(qphy->vdda33)) { - dev_err(dev, "unable to get vdda33 supply\n"); - return PTR_ERR(qphy->vdda33); - } - - qphy->vdda18 = devm_regulator_get(dev, "vdda18"); - if (IS_ERR(qphy->vdda18)) { - dev_err(dev, "unable to get vdda18 supply\n"); - return PTR_ERR(qphy->vdda18); - } + ret = qusb2_get_regulators(qphy); + if (ret) + return ret; mutex_init(&qphy->lock); platform_set_drvdata(pdev, qphy); diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c index 818c5a0e2bcf..4ebebcadcef0 100644 --- a/drivers/usb/phy/phy-msm-snps-hs.c +++ b/drivers/usb/phy/phy-msm-snps-hs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/module.h> @@ -472,15 +472,23 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) if (suspend) { /* Bus suspend */ if (phy->cable_connected || (phy->phy.flags & PHY_HOST_MODE)) { - /* Enable auto-resume functionality by pulsing signal */ - msm_usb_write_readback(phy->base, - USB2_PHY_USB_PHY_HS_PHY_CTRL2, - USB2_AUTO_RESUME, USB2_AUTO_RESUME); - usleep_range(500, 1000); - msm_usb_write_readback(phy->base, - USB2_PHY_USB_PHY_HS_PHY_CTRL2, - USB2_AUTO_RESUME, 0); - + /* Enable auto-resume functionality only when + * there is some peripheral connected and real + * bus suspend happened + */ + if ((phy->phy.flags & PHY_HSFS_MODE) || + (phy->phy.flags & PHY_LS_MODE)) { + /* Enable auto-resume functionality by pulsing + * signal + */ + msm_usb_write_readback(phy->base, + USB2_PHY_USB_PHY_HS_PHY_CTRL2, + USB2_AUTO_RESUME, USB2_AUTO_RESUME); + usleep_range(500, 1000); + msm_usb_write_readback(phy->base, + USB2_PHY_USB_PHY_HS_PHY_CTRL2, + USB2_AUTO_RESUME, 0); + } msm_hsphy_enable_clocks(phy, false); } else {/* Cable disconnect */ mutex_lock(&phy->phy_lock); diff --git a/include/dt-bindings/thermal/qmi_thermal.h b/include/dt-bindings/thermal/qmi_thermal.h index b35c17b8fd0c..38306c2f2754 100644 --- a/include/dt-bindings/thermal/qmi_thermal.h +++ b/include/dt-bindings/thermal/qmi_thermal.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _DT_BINDINGS_QCOM_QMI_THERMAL_H #define _DT_BINDINGS_QCOM_QMI_THERMAL_H @@ -30,6 +30,9 @@ #define QMI_SYS_THERM_1 23 #define QMI_SYS_THERM_2 24 #define QMI_MODEM_TSENS_1 25 +#define QMI_BEAMER_W_THERM 26 +#define QMI_BEAMER_N_THERM 27 +#define QMI_BEAMER_E_THERM 28 #define QMI_MODEM_INST_ID 0x0 #define QMI_ADSP_INST_ID 0x1 diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 6aaf55c42cbc..237a708a0635 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -355,7 +355,7 @@ struct mhi_controller { /* worker for different state transitions */ struct work_struct st_worker; struct work_struct special_work; - struct workqueue_struct *special_wq; + struct workqueue_struct *wq; wait_queue_head_t state_event; diff --git a/include/uapi/drm/msm_drm_pp.h b/include/uapi/drm/msm_drm_pp.h index 264552359d09..34a4833ecf78 100644 --- a/include/uapi/drm/msm_drm_pp.h +++ b/include/uapi/drm/msm_drm_pp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _MSM_DRM_PP_H_ @@ -48,6 +48,7 @@ struct drm_msm_pcc_coeff { * @b_bb: second order coefficients */ #define DRM_MSM_PCC3 +#define NUM_STRUCT_MASK (0xFUL << 60) struct drm_msm_pcc { __u64 flags; struct drm_msm_pcc_coeff r; @@ -118,6 +119,7 @@ struct drm_msm_pa_hsic { * @hue_region: Hue qualifier. * @sat_region: Saturation qualifier. * @val_region: Value qualifier. + * @flags: for customizing operations. */ #define DRM_MSM_MEMCOL struct drm_msm_memcol { @@ -131,6 +133,7 @@ struct drm_msm_memcol { __u32 hue_region; __u32 sat_region; __u32 val_region; + __u64 flags; }; #define DRM_MSM_SIXZONE diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 65ea595e16ab..5bf9bb1414d7 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1495,6 +1495,8 @@ static int select_fallback_rq(int cpu, struct task_struct *p, bool allow_iso) enum { cpuset, possible, fail, bug } state = cpuset; int dest_cpu; int isolated_candidate = -1; + int backup_cpu = -1; + unsigned int max_nr = UINT_MAX; /* * If the node that the CPU is on has been offlined, cpu_to_node() @@ -1510,9 +1512,18 @@ static int select_fallback_rq(int cpu, struct task_struct *p, bool allow_iso) continue; if (cpu_isolated(dest_cpu)) continue; - if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed)) - return dest_cpu; + if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed)) { + if (cpu_rq(dest_cpu)->nr_running < 32) + return dest_cpu; + if (cpu_rq(dest_cpu)->nr_running > max_nr) + continue; + backup_cpu = dest_cpu; + max_nr = cpu_rq(dest_cpu)->nr_running; + } } + + if (backup_cpu != -1) + return backup_cpu; } for (;;) { diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f54224ad5370..0f882639069c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7712,8 +7712,27 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu, /* Bail out if no candidate was found. */ weight = cpumask_weight(candidates); - if (!weight) + if (!weight) { + /* + * Don't overload the previous CPU if it had already + * more runnable tasks. Fallback to a CPU with lower + * number of tasks. + */ + if (cpu_rq(prev_cpu)->nr_running > 32) { + int i; + unsigned int best_nr = UINT_MAX; + + for_each_cpu(i, cpu_active_mask) { + if (!cpumask_test_cpu(i, &p->cpus_allowed)) + continue; + if (cpu_rq(i)->nr_running < best_nr) { + best_nr = cpu_rq(i)->nr_running; + best_energy_cpu = i; + } + } + } goto unlock; + } /* If there is only one sensible candidate, select it now. */ cpu = cpumask_first(candidates); @@ -8774,17 +8793,21 @@ static int detach_tasks(struct lb_env *env) unsigned long load = 0; int detached = 0; int orig_loop = env->loop; + u64 start_t = rq_clock(env->src_rq); lockdep_assert_held(&env->src_rq->lock); if (env->imbalance <= 0) return 0; - if (!same_cluster(env->dst_cpu, env->src_cpu)) - env->flags |= LBF_IGNORE_PREFERRED_CLUSTER_TASKS; + if (env->src_rq->nr_running < 32) { + if (!same_cluster(env->dst_cpu, env->src_cpu)) + env->flags |= LBF_IGNORE_PREFERRED_CLUSTER_TASKS; - if (capacity_orig_of(env->dst_cpu) < capacity_orig_of(env->src_cpu)) - env->flags |= LBF_IGNORE_BIG_TASKS; + if (capacity_orig_of(env->dst_cpu) < + capacity_orig_of(env->src_cpu)) + env->flags |= LBF_IGNORE_BIG_TASKS; + } redo: while (!list_empty(tasks)) { @@ -8802,6 +8825,10 @@ redo: if (env->loop > env->loop_max) break; + /* Abort the loop, if we spent more than 5 msec */ + if (rq_clock(env->src_rq) - start_t > 5000000) + break; + /* take a breather every nr_migrate tasks */ if (env->loop > env->loop_break) { env->loop_break += sched_nr_migrate_break; diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index b841867b7a0b..623f7751d86b 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -416,22 +416,27 @@ void sched_account_irqtime(int cpu, struct task_struct *curr, u64 delta, u64 wallclock) { struct rq *rq = cpu_rq(cpu); - unsigned long flags, nr_windows; + unsigned long nr_windows; u64 cur_jiffies_ts; - raw_spin_lock_irqsave(&rq->lock, flags); - /* - * cputime (wallclock) uses sched_clock so use the same here for - * consistency. + * We called with interrupts disabled. Take the rq lock only + * if we are in idle context in which case update_task_ravg() + * call is needed. */ - delta += sched_clock() - wallclock; - cur_jiffies_ts = get_jiffies_64(); - - if (is_idle_task(curr)) + if (is_idle_task(curr)) { + raw_spin_lock(&rq->lock); + /* + * cputime (wallclock) uses sched_clock so use the same here + * for consistency. + */ + delta += sched_clock() - wallclock; update_task_ravg(curr, rq, IRQ_UPDATE, sched_ktime_clock(), delta); + raw_spin_unlock(&rq->lock); + } + cur_jiffies_ts = get_jiffies_64(); nr_windows = cur_jiffies_ts - rq->irqload_ts; if (nr_windows) { @@ -449,7 +454,6 @@ void sched_account_irqtime(int cpu, struct task_struct *curr, rq->cur_irqload += delta; rq->irqload_ts = cur_jiffies_ts; - raw_spin_unlock_irqrestore(&rq->lock, flags); } /* |