diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/diag/diagfwd_mhi.c | 13 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd_mhi.h | 3 | ||||
-rw-r--r-- | drivers/clk/qcom/clk-aop-qmp.c | 40 | ||||
-rw-r--r-- | drivers/crypto/msm/qce50.c | 7 | ||||
-rw-r--r-- | drivers/gpu/msm/adreno_a5xx.c | 8 | ||||
-rw-r--r-- | drivers/gpu/msm/adreno_a6xx.c | 25 | ||||
-rw-r--r-- | drivers/gpu/msm/adreno_a6xx_gmu.c | 3 | ||||
-rw-r--r-- | drivers/gpu/msm/adreno_a6xx_snapshot.c | 74 | ||||
-rw-r--r-- | drivers/net/wireless/cnss2/main.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/cnss2/main.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/cnss2/pci.c | 71 | ||||
-rw-r--r-- | drivers/net/wireless/cnss2/pci.h | 2 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-smb5.c | 3 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 17 | ||||
-rw-r--r-- | drivers/soc/qcom/icnss2/debug.c | 3 | ||||
-rw-r--r-- | drivers/soc/qcom/icnss2/main.c | 20 | ||||
-rw-r--r-- | drivers/soc/qcom/icnss2/main.h | 1 | ||||
-rw-r--r-- | drivers/soc/qcom/icnss2/qmi.c | 5 |
18 files changed, 293 insertions, 35 deletions
diff --git a/drivers/char/diag/diagfwd_mhi.c b/drivers/char/diag/diagfwd_mhi.c index 4cdda50bae92..d39eee4fbcb2 100644 --- a/drivers/char/diag/diagfwd_mhi.c +++ b/drivers/char/diag/diagfwd_mhi.c @@ -44,6 +44,7 @@ struct diag_mhi_info diag_mhi[NUM_MHI_DEV][NUM_MHI_CHAN] = { .name = "MDM", .enabled = 0, .num_read = 0, + .device_reset = 0, .mempool = POOL_TYPE_MDM, .mempool_init = 0, .mhi_wq = NULL, @@ -61,6 +62,7 @@ struct diag_mhi_info diag_mhi[NUM_MHI_DEV][NUM_MHI_CHAN] = { .name = "MDM_DCI", .enabled = 0, .num_read = 0, + .device_reset = 0, .mempool = POOL_TYPE_MDM_DCI, .mempool_init = 0, .mhi_wq = NULL, @@ -80,6 +82,7 @@ struct diag_mhi_info diag_mhi[NUM_MHI_DEV][NUM_MHI_CHAN] = { .name = "MDM_2", .enabled = 0, .num_read = 0, + .device_reset = 0, .mempool = POOL_TYPE_MDM2, .mempool_init = 0, .mhi_wq = NULL, @@ -97,6 +100,7 @@ struct diag_mhi_info diag_mhi[NUM_MHI_DEV][NUM_MHI_CHAN] = { .name = "MDM_DCI_2", .enabled = 0, .num_read = 0, + .device_reset = 0, .mempool = POOL_TYPE_MDM2_DCI, .mempool_init = 0, .mhi_wq = NULL, @@ -294,6 +298,7 @@ static int __mhi_close(struct diag_mhi_info *mhi_info, int close_flag) } mhi_buf_tbl_clear(mhi_info); diag_remote_dev_close(mhi_info->dev_id); + mhi_info->device_reset = 1; return 0; } @@ -377,6 +382,7 @@ static int __mhi_open(struct diag_mhi_info *mhi_info, int token, int open_flag) } } + mhi_info->device_reset = 0; diag_remote_dev_open(mhi_info->dev_id); queue_work(mhi_info->mhi_wq, &(mhi_info->read_work)); return 0; @@ -661,6 +667,13 @@ static int mhi_fwd_complete(int token, int ch, unsigned char *buf, if (!buf) return -EINVAL; + if (diag_mhi[dev_idx][ch].device_reset) { + DIAG_LOG(DIAG_DEBUG_MHI, + "Device (id: %d, ch: %d) has gone down, skip freeing buffer %pK len:%d\n", + dev_idx, ch, buf, len); + return -ENODEV; + } + DIAG_LOG(DIAG_DEBUG_MHI, "Remove buffer from mhi read table after write completion %pK len:%d\n", buf, len); diff --git a/drivers/char/diag/diagfwd_mhi.h b/drivers/char/diag/diagfwd_mhi.h index ac040948203c..effb11f3bb82 100644 --- a/drivers/char/diag/diagfwd_mhi.h +++ b/drivers/char/diag/diagfwd_mhi.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #ifndef DIAGFWD_MHI_H @@ -60,6 +60,7 @@ struct diag_mhi_info { int mempool; int mempool_init; int num_read; + int device_reset; uint8_t enabled; struct mhi_device *mhi_dev; char name[DIAG_MHI_NAME_SZ]; diff --git a/drivers/clk/qcom/clk-aop-qmp.c b/drivers/clk/qcom/clk-aop-qmp.c index 3d69dc945003..0f7b77d01228 100644 --- a/drivers/clk/qcom/clk-aop-qmp.c +++ b/drivers/clk/qcom/clk-aop-qmp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "%s: " fmt, __func__ @@ -12,6 +12,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/mailbox_client.h> +#include <linux/mailbox_controller.h> #include <dt-bindings/clock/qcom,aop-qmp.h> #define MAX_LEN 96 @@ -216,10 +217,43 @@ DEFINE_CLK_AOP_QMP(qdss_qmp_clk, clock, qdss, QDSS_CLK_LEVEL_DYNAMIC, QDSS_CLK_LEVEL_OFF, CLK_ENABLE_HAND_OFF); DEFINE_CLK_AOP_QMP(qdss_ao_qmp_clk, clock, qdss_ao, QDSS_CLK_LEVEL_DYNAMIC, QDSS_CLK_LEVEL_OFF, 0); +DEFINE_CLK_AOP_QMP(bimc_qmp_clk, ddr, ddr_log, 1, 0, 0); static struct clk_hw *aop_qmp_clk_hws[] = { [QDSS_CLK] = &qdss_qmp_clk.hw, [QDSS_AO_CLK] = &qdss_ao_qmp_clk.hw, + [BIMC_CLK] = &bimc_qmp_clk.hw, +}; + +static int aop_qmp_clk_panic_callback(struct notifier_block *nfb, + unsigned long event, void *unused) +{ + struct qmp_pkt pkt; + struct clk_aop_qmp *clk = &bimc_qmp_clk; + char mbox_msg[MAX_LEN]; + int ret; + + /* + * The mbox channel cannot be used in blocking mode as panic notifier + * callback function is called in atomic context. So update the channel + * to non-blocking mode before sending message. + */ + clk->mbox->cl->tx_block = false; + snprintf(mbox_msg, MAX_LEN, "{class: %s, res: %s, val: 0}", + clk->msg.class, clk->msg.res); + pkt.size = MAX_LEN; + pkt.data = mbox_msg; + + ret = mbox_send_message(clk->mbox, &pkt); + if (ret < 0) + pr_err("BIMC logging request failed, ret %d\n", ret); + + return NOTIFY_OK; +} + +static struct notifier_block aop_qmp_clk_panic_notifier = { + .notifier_call = aop_qmp_clk_panic_callback, + .priority = 1, }; static int qmp_update_client(struct clk_hw *hw, struct device *dev, @@ -319,6 +353,10 @@ static int aop_qmp_clk_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Registered clocks with AOP\n"); + if (of_property_read_bool(np, "qcom,clk-stop-bimc-log")) + atomic_notifier_chain_register(&panic_notifier_list, + &aop_qmp_clk_panic_notifier); + return ret; fail: mbox_free_channel(mbox); diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 959f01eb66db..ea2e7f3931e0 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -2,7 +2,7 @@ /* * QTI Crypto Engine driver. * - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "QCE50: %s: " fmt, __func__ @@ -841,6 +841,11 @@ static int _ce_setup_cipher(struct qce_device *pce_dev, struct qce_req *creq, switch (creq->alg) { case CIPHER_ALG_DES: if (creq->mode != QCE_MODE_ECB) { + if (ivsize > MAX_IV_LENGTH) { + pr_err("%s: error: Invalid length parameter\n", + __func__); + return -EINVAL; + } _byte_stream_to_net_words(enciv32, creq->iv, ivsize); pce = cmdlistinfo->encr_cntr_iv; pce->data = enciv32[0]; diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 6c0ba1a5af34..ad16d09f33bb 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -2843,11 +2843,11 @@ static void a5xx_gpmu_int_callback(struct adreno_device *adreno_dev, int bit) } /* - * a5x_gpc_err_int_callback() - Isr for GPC error interrupts + * a5xx_gpc_err_int_callback() - Isr for GPC error interrupts * @adreno_dev: Pointer to device * @bit: Interrupt bit */ -void a5x_gpc_err_int_callback(struct adreno_device *adreno_dev, int bit) +static void a5xx_gpc_err_int_callback(struct adreno_device *adreno_dev, int bit) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -2857,7 +2857,7 @@ void a5x_gpc_err_int_callback(struct adreno_device *adreno_dev, int bit) * with help of register dump. */ - dev_crit(device->dev, "RBBM: GPC error\n"); + dev_crit_ratelimited(device->dev, "RBBM: GPC error\n"); adreno_irqctrl(adreno_dev, 0); /* Trigger a fault in the dispatcher - this will effect a restart */ @@ -2895,7 +2895,7 @@ static struct adreno_irq_funcs a5xx_irq_funcs[32] = { ADRENO_IRQ_CALLBACK(a5xx_err_callback), /* 6 - RBBM_ATB_ASYNC_OVERFLOW */ ADRENO_IRQ_CALLBACK(a5xx_err_callback), - ADRENO_IRQ_CALLBACK(a5x_gpc_err_int_callback), /* 7 - GPC_ERR */ + ADRENO_IRQ_CALLBACK(a5xx_gpc_err_int_callback), /* 7 - GPC_ERR */ ADRENO_IRQ_CALLBACK(a5xx_preempt_callback),/* 8 - CP_SW */ ADRENO_IRQ_CALLBACK(a5xx_cp_hw_err_callback), /* 9 - CP_HW_ERROR */ /* 10 - CP_CCU_FLUSH_DEPTH_TS */ diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index d1821a7c9076..1a94e7df4e30 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1362,6 +1362,29 @@ static void a6xx_cp_callback(struct adreno_device *adreno_dev, int bit) adreno_dispatcher_schedule(device); } +/* + * a6xx_gpc_err_int_callback() - Isr for GPC error interrupts + * @adreno_dev: Pointer to device + * @bit: Interrupt bit + */ +static void a6xx_gpc_err_int_callback(struct adreno_device *adreno_dev, int bit) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + + /* + * GPC error is typically the result of mistake SW programming. + * Force GPU fault for this interrupt so that we can debug it + * with help of register dump. + */ + + dev_crit_ratelimited(device->dev, "RBBM: GPC error\n"); + adreno_irqctrl(adreno_dev, 0); + + /* Trigger a fault in the dispatcher - this will effect a restart */ + adreno_set_gpu_fault(adreno_dev, ADRENO_SOFT_FAULT); + adreno_dispatcher_schedule(device); +} + #define A6XX_INT_MASK \ ((1 << A6XX_INT_CP_AHB_ERROR) | \ (1 << A6XX_INT_ATB_ASYNCFIFO_OVERFLOW) | \ @@ -1387,7 +1410,7 @@ static struct adreno_irq_funcs a6xx_irq_funcs[32] = { ADRENO_IRQ_CALLBACK(NULL), /* 5 - UNUSED */ /* 6 - RBBM_ATB_ASYNC_OVERFLOW */ ADRENO_IRQ_CALLBACK(a6xx_err_callback), - ADRENO_IRQ_CALLBACK(NULL), /* 7 - GPC_ERR */ + ADRENO_IRQ_CALLBACK(a6xx_gpc_err_int_callback), /* 7 - GPC_ERR */ ADRENO_IRQ_CALLBACK(a6xx_preemption_callback),/* 8 - CP_SW */ ADRENO_IRQ_CALLBACK(a6xx_cp_hw_err_callback), /* 9 - CP_HW_ERROR */ ADRENO_IRQ_CALLBACK(NULL), /* 10 - CP_CCU_FLUSH_DEPTH_TS */ diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index c580165ab7f9..e46118ac548d 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -829,6 +829,9 @@ static bool a6xx_gmu_cx_is_on(struct kgsl_device *device) { unsigned int val; + if (ADRENO_QUIRK(ADRENO_DEVICE(device), ADRENO_QUIRK_CX_GDSC)) + return regulator_is_enabled(KGSL_GMU_DEVICE(device)->cx_gdsc); + gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val); return (val & BIT(31)); } diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 715750b18005..4e444b7a0e2d 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.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 "adreno.h" @@ -621,6 +621,49 @@ static struct a6xx_shader_block a6xx_shader_blocks[] = { {A6XX_HLSQ_INDIRECT_META, 0x40,} }; +static struct a6xx_shader_block a615_shader_blocks[] = { + {A6XX_TP0_TMO_DATA, 0x200}, + {A6XX_TP0_SMO_DATA, 0x80,}, + {A6XX_TP0_MIPMAP_BASE_DATA, 0x3C0}, + {A6XX_TP1_TMO_DATA, 0x200}, + {A6XX_TP1_SMO_DATA, 0x80,}, + {A6XX_TP1_MIPMAP_BASE_DATA, 0x3C0}, + {A6XX_SP_LB_0_DATA, 0x800}, + {A6XX_SP_LB_1_DATA, 0x800}, + {A6XX_SP_LB_2_DATA, 0x800}, + {A6XX_SP_LB_3_DATA, 0x800}, + {A6XX_SP_LB_4_DATA, 0x800}, + {A6XX_SP_LB_5_DATA, 0x200}, + {A6XX_SP_CB_BINDLESS_DATA, 0x800}, + {A6XX_SP_CB_LEGACY_DATA, 0x280,}, + {A6XX_SP_UAV_DATA, 0x80,}, + {A6XX_SP_CB_BINDLESS_TAG, 0x80,}, + {A6XX_SP_TMO_UMO_TAG, 0x80,}, + {A6XX_SP_SMO_TAG, 0x80}, + {A6XX_SP_STATE_DATA, 0x3F}, + {A6XX_HLSQ_CHUNK_CVS_RAM, 0x1C0}, + {A6XX_HLSQ_CHUNK_CPS_RAM, 0x280}, + {A6XX_HLSQ_CHUNK_CVS_RAM_TAG, 0x40,}, + {A6XX_HLSQ_CHUNK_CPS_RAM_TAG, 0x40,}, + {A6XX_HLSQ_ICB_CVS_CB_BASE_TAG, 0x4,}, + {A6XX_HLSQ_ICB_CPS_CB_BASE_TAG, 0x4,}, + {A6XX_HLSQ_CVS_MISC_RAM, 0x1C0}, + {A6XX_HLSQ_CPS_MISC_RAM, 0x580}, + {A6XX_HLSQ_INST_RAM, 0x800}, + {A6XX_HLSQ_GFX_CVS_CONST_RAM, 0x800}, + {A6XX_HLSQ_GFX_CPS_CONST_RAM, 0x800}, + {A6XX_HLSQ_CVS_MISC_RAM_TAG, 0x8,}, + {A6XX_HLSQ_CPS_MISC_RAM_TAG, 0x4,}, + {A6XX_HLSQ_INST_RAM_TAG, 0x80,}, + {A6XX_HLSQ_GFX_CVS_CONST_RAM_TAG, 0xC,}, + {A6XX_HLSQ_GFX_CPS_CONST_RAM_TAG, 0x10}, + {A6XX_HLSQ_PWR_REST_RAM, 0x28}, + {A6XX_HLSQ_PWR_REST_TAG, 0x14}, + {A6XX_HLSQ_DATAPATH_META, 0x40,}, + {A6XX_HLSQ_FRONTEND_META, 0x40}, + {A6XX_HLSQ_INDIRECT_META, 0x40,} +}; + static struct kgsl_memdesc a6xx_capturescript; static struct kgsl_memdesc a6xx_crashdump_registers; static bool crash_dump_valid; @@ -2093,10 +2136,18 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev) * read the data) and then a block specific number of bytes to hold * the data */ - for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) { - script_size += 32 * A6XX_NUM_SHADER_BANKS; - data_size += a6xx_shader_blocks[i].sz * sizeof(unsigned int) * - A6XX_NUM_SHADER_BANKS; + if (adreno_is_a615_family(adreno_dev)) { + for (i = 0; i < ARRAY_SIZE(a615_shader_blocks); i++) { + script_size += 32 * A6XX_NUM_SHADER_BANKS; + data_size += a615_shader_blocks[i].sz * + sizeof(unsigned int) * A6XX_NUM_SHADER_BANKS; + } + } else { + for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) { + script_size += 32 * A6XX_NUM_SHADER_BANKS; + data_size += a6xx_shader_blocks[i].sz * + sizeof(unsigned int) * A6XX_NUM_SHADER_BANKS; + } } /* Calculate the script and data size for MVC registers */ @@ -2202,9 +2253,16 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev) } /* Program each shader block */ - for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) { - ptr += _a6xx_crashdump_init_shader(&a6xx_shader_blocks[i], ptr, - &offset); + if (adreno_is_a615_family(adreno_dev)) { + for (i = 0; i < ARRAY_SIZE(a615_shader_blocks); i++) + ptr += _a6xx_crashdump_init_shader( + &a615_shader_blocks[i], ptr, + &offset); + } else { + for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) + ptr += _a6xx_crashdump_init_shader( + &a6xx_shader_blocks[i], ptr, + &offset); } /* Program the capturescript for the MVC regsiters */ diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index cb79b1fd5957..0c921bf39312 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -41,6 +41,7 @@ #define CNSS_QMI_TIMEOUT_DEFAULT 10000 #define CNSS_BDF_TYPE_DEFAULT CNSS_BDF_ELF #define CNSS_TIME_SYNC_PERIOD_DEFAULT 900000 +#define CNSS_MIN_TIME_SYNC_PERIOD 2000 static struct cnss_plat_data *plat_env; @@ -2098,6 +2099,33 @@ static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv) msm_bus_scale_unregister_client(bus_bw_info->bus_client); } +static ssize_t qtime_sync_period_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", + plat_priv->ctrl_params.time_sync_period); +} + +static ssize_t qtime_sync_period_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int qtime_sync_period = 0; + + if (sscanf(buf, "%du", &qtime_sync_period) != 1) { + cnss_pr_err("Invalid qtime sync sysfs command\n"); + return -EINVAL; + } + + if (qtime_sync_period >= CNSS_MIN_TIME_SYNC_PERIOD) + cnss_pci_update_qtime_sync_period(dev, qtime_sync_period); + + return count; +} + static ssize_t recovery_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -2188,11 +2216,13 @@ static ssize_t fs_ready_store(struct device *dev, static DEVICE_ATTR_WO(fs_ready); static DEVICE_ATTR_WO(shutdown); static DEVICE_ATTR_WO(recovery); +static DEVICE_ATTR_RW(qtime_sync_period); static struct attribute *cnss_attrs[] = { &dev_attr_fs_ready.attr, &dev_attr_shutdown.attr, &dev_attr_recovery.attr, + &dev_attr_qtime_sync_period.attr, NULL, }; diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 7b2dd2cb2f42..b89312925d24 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -458,5 +458,6 @@ int cnss_minidump_add_region(struct cnss_plat_data *plat_priv, int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv, enum cnss_fw_dump_type type, int seg_no, void *va, phys_addr_t pa, size_t size); - +int cnss_pci_update_qtime_sync_period(struct device *dev, + unsigned int qtime_sync_period); #endif /* _CNSS_MAIN_H */ diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index bdf4cd756b73..dcc26de70c5f 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -1365,6 +1365,24 @@ static void cnss_pci_stop_time_sync_update(struct cnss_pci_data *pci_priv) cancel_delayed_work_sync(&pci_priv->time_sync_work); } +int cnss_pci_update_qtime_sync_period(struct device *dev, + unsigned int qtime_sync_period) +{ + struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); + struct cnss_pci_data *pci_priv = plat_priv->bus_priv; + + if (!plat_priv || !pci_priv) + return -ENODEV; + + cnss_pci_stop_time_sync_update(pci_priv); + plat_priv->ctrl_params.time_sync_period = qtime_sync_period; + cnss_pci_start_time_sync_update(pci_priv); + cnss_pr_dbg("WLAN qtime sync period %u\n", + plat_priv->ctrl_params.time_sync_period); + + return 0; +} + int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv) { int ret = 0; @@ -3437,12 +3455,17 @@ static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv) "smmu_iova_ipa"); if (res) { pci_priv->smmu_iova_ipa_start = res->start; + pci_priv->smmu_iova_ipa_current = res->start; pci_priv->smmu_iova_ipa_len = resource_size(res); cnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: 0x%zx\n", &pci_priv->smmu_iova_ipa_start, pci_priv->smmu_iova_ipa_len); } + pci_priv->iommu_geometry = of_property_read_bool(of_node, + "qcom,iommu-geometry"); + cnss_pr_dbg("iommu_geometry: %d\n", pci_priv->iommu_geometry); + of_node_put(of_node); return 0; @@ -3517,10 +3540,11 @@ int cnss_smmu_map(struct device *dev, plat_priv = pci_priv->plat_priv; len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE); - iova = roundup(pci_priv->smmu_iova_ipa_start, PAGE_SIZE); + iova = roundup(pci_priv->smmu_iova_ipa_current, PAGE_SIZE); - if (iova >= - (pci_priv->smmu_iova_ipa_start + pci_priv->smmu_iova_ipa_len)) { + if (pci_priv->iommu_geometry && + iova >= pci_priv->smmu_iova_ipa_start + + pci_priv->smmu_iova_ipa_len) { cnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", iova, &pci_priv->smmu_iova_ipa_start, @@ -3547,6 +3571,8 @@ int cnss_smmu_map(struct device *dev, } } + cnss_pr_dbg("IOMMU map: iova %lx, len %zu\n", iova, len); + ret = iommu_map(pci_priv->iommu_domain, iova, rounddown(paddr, PAGE_SIZE), len, flag); if (ret) { @@ -3554,13 +3580,50 @@ int cnss_smmu_map(struct device *dev, return ret; } - pci_priv->smmu_iova_ipa_start = iova + len; + pci_priv->smmu_iova_ipa_current = iova + len; *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE)); + cnss_pr_dbg("IOMMU map: iova_addr %lx\n", *iova_addr); return 0; } EXPORT_SYMBOL(cnss_smmu_map); +int cnss_smmu_unmap(struct device *dev, uint32_t iova_addr, size_t size) +{ + struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); + unsigned long iova; + size_t unmapped; + size_t len; + + if (!pci_priv) + return -ENODEV; + + iova = rounddown(iova_addr, PAGE_SIZE); + len = roundup(size + iova_addr - iova, PAGE_SIZE); + + if (iova >= pci_priv->smmu_iova_ipa_start + + pci_priv->smmu_iova_ipa_len) { + cnss_pr_err("Out of IOVA space to unmap, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n", + iova, + &pci_priv->smmu_iova_ipa_start, + pci_priv->smmu_iova_ipa_len); + return -ENOMEM; + } + + cnss_pr_dbg("IOMMU unmap: iova %lx, len %zu\n", iova, len); + + unmapped = iommu_unmap(pci_priv->iommu_domain, iova, len); + if (unmapped != len) { + cnss_pr_err("IOMMU unmap failed, unmapped = %zu, requested = %zu\n", + unmapped, len); + return -EINVAL; + } + + pci_priv->smmu_iova_ipa_current = iova; + return 0; +} +EXPORT_SYMBOL(cnss_smmu_unmap); + int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info) { struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index f6d13fb3ea96..32e9ebe85ee6 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -83,6 +83,7 @@ struct cnss_pci_data { dma_addr_t smmu_iova_start; size_t smmu_iova_len; dma_addr_t smmu_iova_ipa_start; + dma_addr_t smmu_iova_ipa_current; size_t smmu_iova_ipa_len; void __iomem *bar; struct cnss_msi_config *msi_config; @@ -101,6 +102,7 @@ struct cnss_pci_data { u32 pcie_reg_size; struct cnss_misc_reg *wlaon_reg; u32 wlaon_reg_size; + u8 iommu_geometry; }; static inline void cnss_set_pci_priv(struct pci_dev *pci_dev, void *data) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 8b0f21fe26cf..ad2e58ef791e 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -465,7 +465,8 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node) chg->pd_not_supported = chg->pd_not_supported || of_property_read_bool(node, "qcom,usb-pd-disable"); - chg->lpd_disabled = of_property_read_bool(node, "qcom,lpd-disable"); + chg->lpd_disabled = chg->lpd_disabled || + of_property_read_bool(node, "qcom,lpd-disable"); rc = of_property_read_u32(node, "qcom,wd-bark-time-secs", &chip->dt.wd_bark_time); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index f9ab3e66f4d6..e93af0fe7a3c 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4531,14 +4531,21 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, /* Sanity checks */ if (ret || !buff_len) { - dev_err(hba->dev, "%s: Failed to get full descriptor length", + dev_err(hba->dev, "%s: Failed to get full descriptor length\n", __func__); return ret; } + if (param_offset >= buff_len || + param_offset + param_size > buff_len) { + dev_err(hba->dev, "%s: Invalid offset 0x%x or size 0x%x in descriptor IDN 0x%x, length 0x%x\n", + __func__, param_offset, param_size, desc_id, buff_len); + return -EINVAL; + } + /* Check whether we need temp memory */ - if (param_offset != 0 || param_size < buff_len) { - desc_buf = kmalloc(buff_len, GFP_KERNEL); + if (param_offset != 0) { + desc_buf = kzalloc(buff_len, GFP_KERNEL); if (!desc_buf) return -ENOMEM; } else { @@ -4552,14 +4559,14 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, desc_buf, &buff_len); if (ret) { - dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d", + dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n", __func__, desc_id, desc_index, param_offset, ret); goto out; } /* Sanity check */ if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) { - dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header", + dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n", __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]); ret = -EINVAL; goto out; diff --git a/drivers/soc/qcom/icnss2/debug.c b/drivers/soc/qcom/icnss2/debug.c index 3771a6b39bab..b3dfbd53cd76 100644 --- a/drivers/soc/qcom/icnss2/debug.c +++ b/drivers/soc/qcom/icnss2/debug.c @@ -407,6 +407,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) continue; case ICNSS_DEL_SERVER: seq_puts(s, "DEL SERVER"); + continue; + case ICNSS_COLD_BOOT_CAL: + seq_puts(s, "COLD BOOT CALIBRATION"); } seq_printf(s, "UNKNOWN-%d", i); diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index a30c403afb4a..56bfb3570726 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -821,8 +821,11 @@ static int icnss_driver_event_fw_init_done(struct icnss_priv *priv, void *data) icnss_pr_info("WLAN FW Initialization done: 0x%lx\n", priv->state); - ret = wlfw_wlan_mode_send_sync_msg(priv, + if (test_bit(ICNSS_COLD_BOOT_CAL, &priv->state)) + ret = wlfw_wlan_mode_send_sync_msg(priv, (enum wlfw_driver_mode_enum_v01)ICNSS_CALIBRATION); + else + icnss_driver_event_fw_ready_ind(priv, NULL); return ret; } @@ -983,10 +986,17 @@ static int icnss_qdss_trace_save_hdlr(struct icnss_priv *priv, static int icnss_event_soc_wake_request(struct icnss_priv *priv, void *data) { int ret = 0; + int count = 0; if (!priv) return -ENODEV; + if (atomic_read(&priv->soc_wake_ref_count)) { + count = atomic_inc_return(&priv->soc_wake_ref_count); + icnss_pr_dbg("SOC already awake, Ref count: %d", count); + return 0; + } + ret = wlfw_send_soc_wake_msg(priv, QMI_WLFW_WAKE_REQUEST_V01); if (!ret) atomic_inc(&priv->soc_wake_ref_count); @@ -2299,7 +2309,6 @@ EXPORT_SYMBOL(icnss_set_fw_log_mode); int icnss_force_wake_request(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); - int count = 0; if (!dev) return -ENODEV; @@ -2311,12 +2320,6 @@ int icnss_force_wake_request(struct device *dev) icnss_pr_dbg("Calling SOC Wake request"); - if (atomic_read(&priv->soc_wake_ref_count)) { - count = atomic_inc_return(&priv->soc_wake_ref_count); - icnss_pr_dbg("SOC already awake, Ref count: %d", count); - return 0; - } - icnss_soc_wake_event_post(priv, ICNSS_SOC_WAKE_REQUEST_EVENT, 0, NULL); @@ -3187,6 +3190,7 @@ static int icnss_probe(struct platform_device *pdev) icnss_runtime_pm_init(priv); icnss_get_cpr_info(priv); + set_bit(ICNSS_COLD_BOOT_CAL, &priv->state); } INIT_LIST_HEAD(&priv->icnss_tcdev_list); diff --git a/drivers/soc/qcom/icnss2/main.h b/drivers/soc/qcom/icnss2/main.h index 82cceb55a1f8..6e4bff30a587 100644 --- a/drivers/soc/qcom/icnss2/main.h +++ b/drivers/soc/qcom/icnss2/main.h @@ -110,6 +110,7 @@ enum icnss_driver_state { ICNSS_BLOCK_SHUTDOWN, ICNSS_PDR, ICNSS_DEL_SERVER, + ICNSS_COLD_BOOT_CAL, }; struct ce_irq_list { diff --git a/drivers/soc/qcom/icnss2/qmi.c b/drivers/soc/qcom/icnss2/qmi.c index c2a8f8a959e3..d053bfcef88c 100644 --- a/drivers/soc/qcom/icnss2/qmi.c +++ b/drivers/soc/qcom/icnss2/qmi.c @@ -1668,12 +1668,17 @@ static void rejuvenate_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, static void cal_done_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, struct qmi_txn *txn, const void *data) { + struct icnss_priv *priv = container_of(qmi, struct icnss_priv, qmi); + icnss_pr_dbg("Received QMI WLFW calibration done indication\n"); if (!txn) { icnss_pr_err("Spurious indication\n"); return; } + + priv->cal_done = true; + clear_bit(ICNSS_COLD_BOOT_CAL, &priv->state); } static void fw_init_done_ind_cb(struct qmi_handle *qmi, |